From 457c5e38218a728ae4abf71e1913463bd55f3c7e Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Tue, 4 Jul 2023 11:10:17 +0800 Subject: [PATCH 01/24] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=8B=89=E6=B5=81?= =?UTF-8?q?=E4=BB=A3=E7=90=86=E6=97=A0=E4=BA=BA=E8=A7=82=E7=9C=8B=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E5=81=9C=E7=94=A8=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../transmit/cmd/impl/SIPCommanderFroPlatform.java | 4 ++-- .../event/request/impl/AckRequestProcessor.java | 4 ++-- .../event/request/impl/ByeRequestProcessor.java | 6 +++--- .../event/request/impl/InviteRequestProcessor.java | 14 +++++++------- .../iot/vmp/media/zlm/ZLMHttpHookListener.java | 2 +- .../iot/vmp/media/zlm/ZLMMediaListManager.java | 4 ++-- .../vmp/service/impl/MediaServerServiceImpl.java | 10 +++++----- .../iot/vmp/service/impl/PlatformServiceImpl.java | 4 ++-- .../iot/vmp/service/impl/PlayServiceImpl.java | 4 ++-- .../service/redisMsg/RedisGbPlayMsgListener.java | 8 ++++---- .../RedisPushStreamCloseResponseListener.java | 4 ++-- .../gb28181/playback/PlaybackController.java | 8 -------- 12 files changed, 32 insertions(+), 40 deletions(-) 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 d9e8197d6..1d4b23ef3 100644 --- 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 @@ -56,7 +56,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { private SipSubscribe sipSubscribe; @Autowired - private ZLMServerFactory ZLMServerFactory; + private ZLMServerFactory zlmServerFactory; @Autowired private SipLayer sipLayer; @@ -820,7 +820,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); if (mediaServerItem != null) { mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc()); - ZLMServerFactory.closeRtpServer(mediaServerItem, sendRtpItem.getStreamId()); + zlmServerFactory.closeRtpServer(mediaServerItem, sendRtpItem.getStreamId()); } SIPRequest byeRequest = headerProviderPlatformProvider.createByeRequest(parentPlatform, sendRtpItem); if (byeRequest == null) { 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 c9a38c665..07946eb8c 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 @@ -67,7 +67,7 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In private IVideoManagerStorage storager; @Autowired - private ZLMServerFactory ZLMServerFactory; + private ZLMServerFactory zlmServerFactory; @Autowired private ZlmHttpHookSubscribe hookSubscribe; @@ -140,7 +140,7 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, jsonObject, param, callIdHeader); }); }else { - JSONObject startSendRtpStreamResult = ZLMServerFactory.startSendRtpStream(mediaInfo, param); + JSONObject startSendRtpStreamResult = zlmServerFactory.startSendRtpStream(mediaInfo, param); if (startSendRtpStreamResult != null) { startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, startSendRtpStreamResult, param, callIdHeader); } 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 b7ecd1e60..374e5dcc0 100644 --- 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 @@ -64,7 +64,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In private IVideoManagerStorage storager; @Autowired - private ZLMServerFactory ZLMServerFactory; + private ZLMServerFactory zlmServerFactory; @Autowired private SSRCFactory ssrcFactory; @@ -115,7 +115,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(), callIdHeader.getCallId(), null); - ZLMServerFactory.stopSendRtpStream(mediaInfo, param); + zlmServerFactory.stopSendRtpStream(mediaInfo, param); if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) { ParentPlatform platform = platformService.queryPlatformByServerGBId(sendRtpItem.getPlatformId()); if (platform != null) { @@ -129,7 +129,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In } } - int totalReaderCount = ZLMServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId); + int totalReaderCount = zlmServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId); if (totalReaderCount <= 0) { logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId); if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) { 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 f499705ba..c0a1fec9c 100644 --- 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 @@ -91,7 +91,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements private SIPSender sipSender; @Autowired - private ZLMServerFactory ZLMServerFactory; + private ZLMServerFactory zlmServerFactory; @Autowired private IMediaServerService mediaServerService; @@ -345,7 +345,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements streamTypeStr = "UDP"; } logger.info("[上级Invite] {}, 平台:{}, 通道:{}, 收流地址:{}:{},收流方式:{}, ssrc:{}", sessionName, username, channelId, addressStr, port, streamTypeStr, ssrc); - SendRtpItem sendRtpItem = ZLMServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, + SendRtpItem sendRtpItem = zlmServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, device.getDeviceId(), channelId, mediaTransmissionTCP, platform.isRtcp()); if (tcpActive != null) { @@ -548,10 +548,10 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements CallIdHeader callIdHeader, MediaServerItem 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 = zlmServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream()); if (streamReady != null && streamReady) { // 自平台内容 - SendRtpItem sendRtpItem = ZLMServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, + SendRtpItem sendRtpItem = zlmServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp()); if (sendRtpItem == null) { @@ -587,10 +587,10 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements String channelId, String addressStr, String ssrc, String requesterId) { // 推流 if (streamPushItem.isSelf()) { - Boolean streamReady = ZLMServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream()); + Boolean streamReady = zlmServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream()); if (streamReady != null && streamReady) { // 自平台内容 - SendRtpItem sendRtpItem = ZLMServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, + SendRtpItem sendRtpItem = zlmServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp()); if (sendRtpItem == null) { @@ -706,7 +706,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements mediaListManager.addChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream(), (app, stream, serverId) -> { dynamicTask.stop(callIdHeader.getCallId()); if (serverId.equals(userSetting.getServerId())) { - SendRtpItem sendRtpItem = ZLMServerFactory.createSendRtpItem(mediaServerItem, addressStr, finalPort, ssrc, requesterId, + SendRtpItem sendRtpItem = zlmServerFactory.createSendRtpItem(mediaServerItem, addressStr, finalPort, ssrc, requesterId, app, stream, channelId, mediaTransmissionTCP, platform.isRtcp()); if (sendRtpItem == null) { 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 8151feffa..e1e879d39 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java @@ -506,7 +506,7 @@ public class ZLMHttpHookListener { // 拉流代理 StreamProxyItem streamProxyItem = streamProxyService.getStreamProxyByAppAndStream(param.getApp(), param.getStream()); if (streamProxyItem != null) { - if (streamProxyItem.isEnableDisableNoneReader()) { + if (streamProxyItem.isEnableRemoveNoneReader()) { // 无人观看自动移除 ret.put("close", true); streamProxyService.del(param.getApp(), param.getStream()); 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 41ef4d07c..cbc5fde6e 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java @@ -61,7 +61,7 @@ public class ZLMMediaListManager { private UserSetting userSetting; @Autowired - private ZLMServerFactory ZLMServerFactory; + private ZLMServerFactory zlmServerFactory; @Autowired private IMediaServerService mediaServerService; @@ -97,7 +97,7 @@ public class ZLMMediaListManager { public void sendStreamEvent(String app, String stream, String mediaServerId) { MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); // 查看推流状态 - Boolean streamReady = ZLMServerFactory.isStreamReady(mediaServerItem, app, stream); + Boolean streamReady = zlmServerFactory.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/service/impl/MediaServerServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java index 9d4a9dcb8..a79b4108a 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 @@ -87,7 +87,7 @@ public class MediaServerServiceImpl implements IMediaServerService { @Autowired - private ZLMServerFactory ZLMServerFactory; + private ZLMServerFactory zlmServerFactory; @Autowired private EventPublisher publisher; @@ -181,7 +181,7 @@ public class MediaServerServiceImpl implements IMediaServerService { } int rtpServerPort; if (mediaServerItem.isRtpEnable()) { - rtpServerPort = ZLMServerFactory.createRTPServer(mediaServerItem, streamId, ssrcCheck?Integer.parseInt(ssrc):0, port, reUsePort, tcpMode); + rtpServerPort = zlmServerFactory.createRTPServer(mediaServerItem, streamId, ssrcCheck?Integer.parseInt(ssrc):0, port, reUsePort, tcpMode); } else { rtpServerPort = mediaServerItem.getRtpProxyPort(); } @@ -193,7 +193,7 @@ public class MediaServerServiceImpl implements IMediaServerService { if (mediaServerItem == null) { return; } - ZLMServerFactory.closeRtpServer(mediaServerItem, streamId); + zlmServerFactory.closeRtpServer(mediaServerItem, streamId); } @Override @@ -202,7 +202,7 @@ public class MediaServerServiceImpl implements IMediaServerService { callback.run(false); return; } - ZLMServerFactory.closeRtpServer(mediaServerItem, streamId, callback); + zlmServerFactory.closeRtpServer(mediaServerItem, streamId, callback); } @Override @@ -213,7 +213,7 @@ public class MediaServerServiceImpl implements IMediaServerService { @Override public Boolean updateRtpServerSSRC(MediaServerItem mediaServerItem, String streamId, String ssrc) { - return ZLMServerFactory.updateRtpServerSSRC(mediaServerItem, streamId, ssrc); + return zlmServerFactory.updateRtpServerSSRC(mediaServerItem, streamId, ssrc); } @Override 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 a9d4cee2c..b75b47710 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java @@ -69,7 +69,7 @@ public class PlatformServiceImpl implements IPlatformService { private DynamicTask dynamicTask; @Autowired - private ZLMServerFactory ZLMServerFactory; + private ZLMServerFactory zlmServerFactory; @Autowired private SubscribeHolder subscribeHolder; @@ -338,7 +338,7 @@ public class PlatformServiceImpl implements IPlatformService { param.put("vhost", "__defaultVhost__"); param.put("app", sendRtpItem.getApp()); param.put("stream", sendRtpItem.getStreamId()); - ZLMServerFactory.stopSendRtpStream(mediaInfo, param); + zlmServerFactory.stopSendRtpStream(mediaInfo, param); } } } 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 397fb76ba..519013920 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 @@ -81,7 +81,7 @@ public class PlayServiceImpl implements IPlayService { private ZLMRESTfulUtils zlmresTfulUtils; @Autowired - private ZLMServerFactory ZLMServerFactory; + private ZLMServerFactory zlmServerFactory; @Autowired private AssistRESTfulUtils assistRESTfulUtils; @@ -142,7 +142,7 @@ public class PlayServiceImpl implements IPlayService { String mediaServerId = streamInfo.getMediaServerId(); MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); - Boolean ready = ZLMServerFactory.isStreamReady(mediaInfo, "rtp", streamId); + Boolean ready = zlmServerFactory.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, 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 9b8e31294..2b0f366bd 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java @@ -72,7 +72,7 @@ public class RedisGbPlayMsgListener implements MessageListener { private RedisTemplate redisTemplate; @Autowired - private ZLMServerFactory ZLMServerFactory; + private ZLMServerFactory zlmServerFactory; @Autowired private IMediaServerService mediaServerService; @@ -230,7 +230,7 @@ public class RedisGbPlayMsgListener implements MessageListener { param.put("pt", requestPushStreamMsg.getPt()); param.put("use_ps", requestPushStreamMsg.isPs() ? "1" : "0"); param.put("only_audio", requestPushStreamMsg.isOnlyAudio() ? "1" : "0"); - JSONObject jsonObject = ZLMServerFactory.startSendRtpStream(mediaInfo, param); + JSONObject jsonObject = zlmServerFactory.startSendRtpStream(mediaInfo, param); // 回复消息 responsePushStream(jsonObject, fromId, serial); } @@ -267,7 +267,7 @@ public class RedisGbPlayMsgListener implements MessageListener { return; } // 确定流是否在线 - Boolean streamReady = ZLMServerFactory.isStreamReady(mediaServerItem, content.getApp(), content.getStream()); + Boolean streamReady = zlmServerFactory.isStreamReady(mediaServerItem, content.getApp(), content.getStream()); if (streamReady != null && streamReady) { logger.info("[回复推流信息] {}/{}", content.getApp(), content.getStream()); responseSendItem(mediaServerItem, content, toId, serial); @@ -311,7 +311,7 @@ public class RedisGbPlayMsgListener implements MessageListener { * 将获取到的sendItem发送出去 */ private void responseSendItem(MediaServerItem mediaServerItem, RequestSendItemMsg content, String toId, String serial) { - SendRtpItem sendRtpItem = ZLMServerFactory.createSendRtpItem(mediaServerItem, content.getIp(), + SendRtpItem sendRtpItem = zlmServerFactory.createSendRtpItem(mediaServerItem, content.getIp(), content.getPort(), content.getSsrc(), content.getPlatformId(), content.getApp(), content.getStream(), content.getChannelId(), content.getTcp(), content.getRtcp()); 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 4b52f72fd..ad00baf7e 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamCloseResponseListener.java +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamCloseResponseListener.java @@ -58,7 +58,7 @@ public class RedisPushStreamCloseResponseListener implements MessageListener { private IMediaServerService mediaServerService; @Autowired - private ZLMServerFactory ZLMServerFactory; + private ZLMServerFactory zlmServerFactory; private Map responseEvents = new ConcurrentHashMap<>(); @@ -89,7 +89,7 @@ public class RedisPushStreamCloseResponseListener implements MessageListener { logger.info("[REDIS消息-推流结束] 停止向上级推流:{}", streamId); MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(), sendRtpItem.getCallId(), sendRtpItem.getStreamId()); - ZLMServerFactory.stopSendRtpStream(mediaInfo, param); + zlmServerFactory.stopSendRtpStream(mediaInfo, param); try { commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem); diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java index 84ccc0b6d..d3225a219 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java @@ -11,11 +11,9 @@ import com.genersoft.iot.vmp.gb28181.bean.Device; 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.ZLMServerFactory; 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 com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import com.genersoft.iot.vmp.vmanager.bean.StreamContent; @@ -53,15 +51,9 @@ public class PlaybackController { @Autowired private SIPCommander cmder; - @Autowired - private ZLMServerFactory ZLMServerFactory; - @Autowired private IVideoManagerStorage storager; - @Autowired - private IRedisCatchStorage redisCatchStorage; - @Autowired private IInviteStreamService inviteStreamService; From deeff5533b2dd30ab7b74ca83bee9a7b39faf1d9 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Wed, 5 Jul 2023 17:20:20 +0800 Subject: [PATCH 02/24] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=85=BC=E5=AE=B9?= =?UTF-8?q?=E7=9B=AE=E5=BD=95=E5=90=8C=E6=AD=A5=E5=85=BC=E5=AE=B9=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../genersoft/iot/vmp/gb28181/utils/XmlUtil.java | 13 +++++++++---- .../iot/vmp/media/zlm/ZLMHttpHookListener.java | 2 -- 2 files changed, 9 insertions(+), 6 deletions(-) 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 a83e7c9fb..a08231c87 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 @@ -380,13 +380,18 @@ public class XmlUtil { } } // 父设备/区域/系统ID - String realParentId = parentID; - if (!ObjectUtils.isEmpty(parentID)) { + + if (!ObjectUtils.isEmpty(parentID) ) { if (parentID.contains("/")) { String[] parentIdArray = parentID.split("/"); - realParentId = parentIdArray[parentIdArray.length - 1]; + deviceChannel.setParentId(parentIdArray[parentIdArray.length - 1]); + }else { + if (parentID.length()%2 == 0) { + deviceChannel.setParentId(parentID); + }else { + logger.warn("[xml解析] 不规范的parentID:{}, 已舍弃", parentID); + } } - deviceChannel.setParentId(realParentId); }else { if (!ObjectUtils.isEmpty(businessGroupID)) { deviceChannel.setParentId(businessGroupID); 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 e1e879d39..eac7401df 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java @@ -447,8 +447,6 @@ public class ZLMHttpHookListener { if ("rtp".equals(param.getApp())) { ret.put("close", userSetting.getStreamOnDemand()); // 国标流, 点播/录像回放/录像下载 -// StreamInfo streamInfoForPlayCatch = redisCatchStorage.queryPlayByStreamId(param.getStream()); - InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, param.getStream()); // 点播 if (inviteInfo != null) { From 0a3d25fb5b54bc55ea70ac5ac209728c09f028dd Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Thu, 6 Jul 2023 15:07:16 +0800 Subject: [PATCH 03/24] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=9D=9E=E5=BF=85?= =?UTF-8?q?=E4=BC=A0=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/vmp/vmanager/rtp/RtpController.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) 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 5c74fcc95..311a007ae 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 @@ -28,10 +28,8 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.util.ObjectUtils; +import org.springframework.web.bind.annotation.*; import java.io.IOException; import java.util.HashMap; @@ -95,7 +93,7 @@ public class RtpController { @Parameter(name = "stream", description = "形成的流的ID", required = true) @Parameter(name = "tcpMode", description = "收流模式, 0为UDP, 1为TCP被动", required = true) @Parameter(name = "callBack", description = "回调地址,如果收流超时会通道回调通知,回调为get请求,参数为callId", required = true) - public OtherRtpSendInfo openRtpServer(Boolean isSend, String ssrc, String callId, String stream, Integer tcpMode, String callBack) { + public OtherRtpSendInfo openRtpServer(Boolean isSend, @RequestParam(required = false)String ssrc, String callId, String stream, Integer tcpMode, String callBack) { logger.info("[第三方服务对接->开启收流和获取发流信息] isSend->{}, ssrc->{}, callId->{}, stream->{}, tcpMode->{}, callBack->{}", isSend, ssrc, callId, stream, tcpMode==0?"UDP":"TCP被动", callBack); @@ -159,7 +157,7 @@ public class RtpController { logger.info("[第三方服务对接->开启收流和获取发流信息] 端口保持超时 callId->{}", callId); redisTemplate.delete(key); zlmServerFactory.releasePort(mediaServerItem, callId); - }, 300000); + }, 15000); otherRtpSendInfo.setIp(mediaServerItem.getSdpIp()); otherRtpSendInfo.setPort(port); logger.info("[开启收流和获取发流信息] 结果,callId->{}, {}", callId, otherRtpSendInfo); @@ -189,9 +187,12 @@ public class RtpController { @Parameter(name = "onlyAudio", description = "是否只有音频", required = true) @Parameter(name = "isUdp", description = "是否为UDP", required = true) @Parameter(name = "streamType", description = "流类型,1为es流,2为ps流, 默认es流", required = false) - public void sendRTP(String ssrc, String ip, Integer port, String app, String stream, String callId, Boolean onlyAudio, Boolean isUdp, Integer streamType) { + public void sendRTP(String ssrc, String ip, Integer port, String app, String stream, String callId, Boolean onlyAudio, Boolean isUdp, @RequestParam(required = false)Integer streamType) { logger.info("[第三方服务对接->发送流] ssrc->{}, ip->{}, port->{}, app->{}, stream->{}, callId->{}, onlyAudio->{}, streamType->{}", ssrc, ip, port, app, stream, callId, onlyAudio, streamType == 1? "ES":"PS"); + if (ObjectUtils.isEmpty(streamType)) { + streamType = 1; + } MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer(); String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + callId; OtherRtpSendInfo sendInfo = (OtherRtpSendInfo)redisTemplate.opsForValue().get(key); From e163cf4d202e7fe8fb35e29999eeb53e4f525a71 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Thu, 6 Jul 2023 15:18:10 +0800 Subject: [PATCH 04/24] =?UTF-8?q?=E5=85=BC=E5=AE=B9=E6=B5=B7=E5=BA=B7?= =?UTF-8?q?=E5=B9=B3=E5=8F=B0=E5=9C=A8address=E5=AD=97=E6=AE=B5=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E9=94=99=E8=AF=AF=E7=9A=84<=E6=88=96>=E7=A0=B4?= =?UTF-8?q?=E5=9D=8Fxml=E7=BB=93=E6=9E=84=E7=9A=84=E6=83=85=E5=86=B5?= =?UTF-8?q?=EF=BC=8C=20#903?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../request/SIPRequestProcessorParent.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java index 0a7eb2c9a..d52f4f6a1 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java @@ -199,7 +199,24 @@ public abstract class SIPRequestProcessorParent { Byte[] bytes = new Byte[0]; byte[] bytesResult = ArrayUtils.toPrimitive(result.toArray(bytes)); - Document xml = reader.read(new ByteArrayInputStream(bytesResult)); + Document xml; + try { + xml = reader.read(new ByteArrayInputStream(bytesResult)); + }catch (DocumentException e) { + logger.warn("[xml解析异常]: 愿文如下: \r\n{}", new String(bytesResult)); + logger.warn("[xml解析异常]: 愿文如下: 尝试兼容性处理"); + String[] xmlLineArray = new String(bytesResult).split("\\r?\\n"); + + // 兼容海康的address字段带有<破换xml结构导致无法解析xml的问题 + StringBuilder stringBuilder = new StringBuilder(); + for (String s : xmlLineArray) { + if (s.startsWith(" Date: Thu, 6 Jul 2023 15:35:59 +0800 Subject: [PATCH 05/24] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E5=AF=BC=E8=87=B4=E6=97=A0=E6=B3=95=E8=BD=AC?= =?UTF-8?q?=E6=88=90JSON=E8=BF=94=E5=9B=9E=20=20#919?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/vmp/gb28181/bean/Device.java | 3 +++ .../impl/RegisterRequestProcessor.java | 11 ++++++++++ .../vmp/service/impl/DeviceServiceImpl.java | 22 ++++++++++++++----- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java index 1318c59c5..1c7baac9c 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java @@ -244,6 +244,9 @@ public class Device { } public Integer getStreamModeForParam() { + if (streamMode == null) { + return 0; + } if (streamMode.equalsIgnoreCase("UDP")) { return 0; }else if (streamMode.equalsIgnoreCase("TCP-PASSIVE")) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java index 6eea02ff8..e084f3523 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java @@ -166,7 +166,18 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen device.setGeoCoordSys("WGS84"); device.setDeviceId(deviceId); device.setOnLine(false); + }else { + if (ObjectUtils.isEmpty(device.getStreamMode())) { + device.setStreamMode("UDP"); + } + if (ObjectUtils.isEmpty(device.getCharset())) { + device.setCharset("GB2312"); + } + if (ObjectUtils.isEmpty(device.getGeoCoordSys())) { + device.setGeoCoordSys("WGS84"); + } } + device.setIp(remoteAddressInfo.getIp()); device.setPort(remoteAddressInfo.getPort()); device.setHostAddress(remoteAddressInfo.getIp().concat(":").concat(String.valueOf(remoteAddressInfo.getPort()))); 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 c288ff46c..6e748f4f3 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java @@ -493,8 +493,12 @@ public class DeviceServiceImpl implements IDeviceService { if (!ObjectUtils.isEmpty(device.getMediaServerId())) { deviceInStore.setMediaServerId(device.getMediaServerId()); } - deviceInStore.setSdpIp(device.getSdpIp()); - deviceInStore.setCharset(device.getCharset()); + if (!ObjectUtils.isEmpty(device.getCharset())) { + deviceInStore.setCharset(device.getCharset()); + } + if (!ObjectUtils.isEmpty(device.getSdpIp())) { + deviceInStore.setSdpIp(device.getSdpIp()); + } // 目录订阅相关的信息 if (device.getSubscribeCycleForCatalog() > 0) { @@ -525,10 +529,18 @@ public class DeviceServiceImpl implements IDeviceService { removeMobilePositionSubscribe(deviceInStore); } } - // 坐标系变化,需要重新计算GCJ02坐标和WGS84坐标 - if (!deviceInStore.getGeoCoordSys().equals(device.getGeoCoordSys())) { - updateDeviceChannelGeoCoordSys(device); + if (deviceInStore.getGeoCoordSys() != null) { + // 坐标系变化,需要重新计算GCJ02坐标和WGS84坐标 + if (!deviceInStore.getGeoCoordSys().equals(device.getGeoCoordSys())) { + updateDeviceChannelGeoCoordSys(device); + } + }else { + device.setGeoCoordSys("WGS84"); } + if (device.getCharset() == null) { + device.setCharset("GB2312"); + } + // 更新redis redisCatchStorage.updateDevice(device); deviceMapper.updateCustom(device); From fd434b3cf2147d8192e0d8b4b271e67bac19560c Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Thu, 6 Jul 2023 15:55:58 +0800 Subject: [PATCH 06/24] =?UTF-8?q?=E4=BF=AE=E5=A4=8DBUG=20#928?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java | 3 --- 1 file changed, 3 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 9ac6ab930..71711389c 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 @@ -130,9 +130,6 @@ public class StreamProxyServiceImpl implements IStreamProxyService { port = mediaInfo.getRtspPort(); schemaForUri = schema; }else if (schema.equalsIgnoreCase("flv")) { - port = mediaInfo.getHttpPort(); - schemaForUri = "http"; - }else if (schema.equalsIgnoreCase("rtmp")) { port = mediaInfo.getRtmpPort(); schemaForUri = schema; }else { From 9fc9a29811ec47bc057a82cd6014df4fa83a64b8 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Thu, 6 Jul 2023 18:01:16 +0800 Subject: [PATCH 07/24] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=B5=B7=E5=BA=B7?= =?UTF-8?q?=E5=8F=91=E9=80=81=E9=95=BF=E5=BA=A6=E4=B8=8E=E5=AE=9E=E9=99=85?= =?UTF-8?q?=E9=95=BF=E5=BA=A6=E4=B8=8D=E4=B8=80=E8=87=B4=E7=9A=84=E6=83=85?= =?UTF-8?q?=E5=86=B5=EF=BC=8C=E5=AF=BC=E8=87=B4=E6=97=A0=E6=B3=95=E8=AF=86?= =?UTF-8?q?=E5=88=AB=E6=B6=88=E6=81=AF=E5=86=85=E5=AE=B9=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java | 2 ++ 1 file changed, 2 insertions(+) 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 59fa8f6de..18ccaf410 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 @@ -31,6 +31,8 @@ public class DefaultProperties { properties.setProperty("gov.nist.javax.sip.CANCEL_CLIENT_TRANSACTION_CHECKED", "true"); // 为_NULL _对话框传递_终止的_事件 properties.setProperty("gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_NULL_DIALOG", "true"); + // 是否自动计算content length的实际长度,默认不计算 + properties.setProperty("gov.nist.javax.sip.COMPUTE_CONTENT_LENGTH_FROM_MESSAGE_BODY", "true"); // 会话清理策略 properties.setProperty("gov.nist.javax.sip.RELEASE_REFERENCES_STRATEGY", "Normal"); // 处理由该服务器处理的基于底层TCP的保持生存超时 From ff1e9f79c2992777fb7a1ecaeb85c8acb1250535 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Fri, 7 Jul 2023 14:51:41 +0800 Subject: [PATCH 08/24] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=B5=B7=E5=BA=B7?= =?UTF-8?q?=E5=8F=91=E9=80=81=E7=9A=84Message=E6=B6=88=E6=81=AF=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E7=9A=84=E6=B6=88=E6=81=AF=E4=BD=93=E9=95=BF=E5=BA=A6?= =?UTF-8?q?=E4=B8=BA0=EF=BC=8C=E5=AF=BC=E8=87=B4=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E8=A7=A3=E6=9E=90=E7=9A=84=E9=97=AE=E9=A2=98=20=20#920?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../genersoft/iot/vmp/gb28181/SipLayer.java | 3 +- .../vmp/gb28181/bean/GBStringMsgParser.java | 457 ++++++++++++++++++ .../bean/{WvpSipDate.java => GbSipDate.java} | 4 +- .../bean/GbStringMsgParserFactory.java | 21 + .../impl/RegisterRequestProcessor.java | 10 +- .../vmanager/gb28181/device/DeviceQuery.java | 1 - 6 files changed, 487 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/genersoft/iot/vmp/gb28181/bean/GBStringMsgParser.java rename src/main/java/com/genersoft/iot/vmp/gb28181/bean/{WvpSipDate.java => GbSipDate.java} (97%) create mode 100644 src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbStringMsgParserFactory.java 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 5a8db1783..90b5291e8 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181; import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.UserSetting; +import com.genersoft.iot.vmp.gb28181.bean.GbStringMsgParserFactory; import com.genersoft.iot.vmp.gb28181.conf.DefaultProperties; import com.genersoft.iot.vmp.gb28181.transmit.ISIPProcessorObserver; import gov.nist.javax.sip.SipProviderImpl; @@ -63,6 +64,7 @@ public class SipLayer implements CommandLineRunner { SipStackImpl sipStack; try { sipStack = (SipStackImpl)SipFactory.getInstance().createSipStack(DefaultProperties.getProperties(monitorIp, userSetting.getSipLog())); + sipStack.setMessageParserFactory(new GbStringMsgParserFactory()); } catch (PeerUnavailableException e) { logger.error("[SIP SERVER] SIP服务启动失败, 监听地址{}失败,请检查ip是否正确", monitorIp); return; @@ -75,7 +77,6 @@ public class SipLayer implements CommandLineRunner { tcpSipProvider.setDialogErrorsAutomaticallyHandled(); tcpSipProvider.addSipListener(sipProcessorObserver); tcpSipProviderMap.put(monitorIp, tcpSipProvider); - logger.info("[SIP SERVER] tcp://{}:{} 启动成功", monitorIp, port); } catch (TransportNotSupportedException | TooManyListenersException diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/GBStringMsgParser.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/GBStringMsgParser.java new file mode 100644 index 000000000..2abc3569a --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/GBStringMsgParser.java @@ -0,0 +1,457 @@ +package com.genersoft.iot.vmp.gb28181.bean; + +import gov.nist.core.CommonLogger; +import gov.nist.core.Host; +import gov.nist.core.HostNameParser; +import gov.nist.core.StackLogger; +import gov.nist.javax.sip.SIPConstants; +import gov.nist.javax.sip.address.AddressImpl; +import gov.nist.javax.sip.address.GenericURI; +import gov.nist.javax.sip.address.SipUri; +import gov.nist.javax.sip.address.TelephoneNumber; +import gov.nist.javax.sip.header.*; +import gov.nist.javax.sip.message.SIPMessage; +import gov.nist.javax.sip.message.SIPRequest; +import gov.nist.javax.sip.message.SIPResponse; +import gov.nist.javax.sip.parser.*; + +import java.io.UnsupportedEncodingException; +import java.text.ParseException; + +public class GBStringMsgParser implements MessageParser { + + protected static boolean computeContentLengthFromMessage = false; + + private static StackLogger logger = CommonLogger.getLogger(StringMsgParser.class); + + /** + * @since v0.9 + */ + public GBStringMsgParser() { + super(); + } + + /** + * Parse a buffer containing a single SIP Message where the body is an array + * of un-interpreted bytes. This is intended for parsing the message from a + * memory buffer when the buffer. Incorporates a bug fix for a bug that was + * noted by Will Sullin of Callcast + * + * @param msgBuffer + * a byte buffer containing the messages to be parsed. This can + * consist of multiple SIP Messages concatenated together. + * @return a SIPMessage[] structure (request or response) containing the + * parsed SIP message. + * @exception ParseException + * is thrown when an illegal message has been encountered + * (and the rest of the buffer is discarded). + * @see ParseExceptionListener + */ + public SIPMessage parseSIPMessage(byte[] msgBuffer, boolean readBody, boolean strict, ParseExceptionListener parseExceptionListener) throws ParseException { + if (msgBuffer == null || msgBuffer.length == 0) + return null; + + int i = 0; + + // Squeeze out any leading control character. + try { + while (msgBuffer[i] < 0x20) + i++; + } + catch (ArrayIndexOutOfBoundsException e) { + // Array contains only control char, return null. + if (logger.isLoggingEnabled(StackLogger.TRACE_DEBUG)) { + logger.logDebug("handled only control char so returning null"); + } + return null; + } + + // Iterate thru the request/status line and headers. + String currentLine = null; + String currentHeader = null; + boolean isFirstLine = true; + SIPMessage message = null; + do + { + int lineStart = i; + + // Find the length of the line. + try { + while (msgBuffer[i] != '\r' && msgBuffer[i] != '\n') + i++; + } + catch (ArrayIndexOutOfBoundsException e) { + // End of the message. + break; + } + int lineLength = i - lineStart; + + // Make it a String. + try { + currentLine = new String(msgBuffer, lineStart, lineLength, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new ParseException("Bad message encoding!", 0); + } + + currentLine = trimEndOfLine(currentLine); + + if (currentLine.length() == 0) { + // Last header line, process the previous buffered header. + if (currentHeader != null && message != null) { + processHeader(currentHeader, message, parseExceptionListener, msgBuffer); + } + + } + else { + if (isFirstLine) { + message = processFirstLine(currentLine, parseExceptionListener, msgBuffer); + } else { + char firstChar = currentLine.charAt(0); + if (firstChar == '\t' || firstChar == ' ') { + if (currentHeader == null) + throw new ParseException("Bad header continuation.", 0); + + // This is a continuation, append it to the previous line. + currentHeader += currentLine.substring(1); + } + else { + if (currentHeader != null && message != null) { + processHeader(currentHeader, message, parseExceptionListener, msgBuffer); + } + currentHeader = currentLine; + } + } + } + + if (msgBuffer[i] == '\r' && msgBuffer.length > i+1 && msgBuffer[i+1] == '\n') + i++; + + i++; + + isFirstLine = false; + } while (currentLine.length() > 0); // End do - while + + if (message == null) throw new ParseException("Bad message", 0); + message.setSize(i); + + // Check for content legth header + if (readBody && message.getContentLength() != null ) { + if ( message.getContentLength().getContentLength() != 0) { + int bodyLength = msgBuffer.length - i; + + byte[] body = new byte[bodyLength]; + System.arraycopy(msgBuffer, i, body, 0, bodyLength); + message.setMessageContent(body,!strict,computeContentLengthFromMessage,message.getContentLength().getContentLength()); + } else if (message.getCSeqHeader().getMethod().equalsIgnoreCase("MESSAGE")) { + int bodyLength = msgBuffer.length - i; + + byte[] body = new byte[bodyLength]; + System.arraycopy(msgBuffer, i, body, 0, bodyLength); + message.setMessageContent(body,!strict,computeContentLengthFromMessage,bodyLength); + }else if (!computeContentLengthFromMessage && strict) { + String last4Chars = new String(msgBuffer, msgBuffer.length - 4, 4); + if(!"\r\n\r\n".equals(last4Chars)) { + throw new ParseException("Extraneous characters at the end of the message ",i); + } + } + } + + return message; + } + + protected static String trimEndOfLine(String line) { + if (line == null) + return line; + + int i = line.length() - 1; + while (i >= 0 && line.charAt(i) <= 0x20) + i--; + + if (i == line.length() - 1) + return line; + + if (i == -1) + return ""; + + return line.substring(0, i+1); + } + + protected SIPMessage processFirstLine(String firstLine, ParseExceptionListener parseExceptionListener, byte[] msgBuffer) throws ParseException { + SIPMessage message; + if (!firstLine.startsWith(SIPConstants.SIP_VERSION_STRING)) { + message = new SIPRequest(); + try { + RequestLine requestLine = new RequestLineParser(firstLine + "\n") + .parse(); + ((SIPRequest) message).setRequestLine(requestLine); + } catch (ParseException ex) { + if (parseExceptionListener != null) + try { + parseExceptionListener.handleException(ex, message, + RequestLine.class, firstLine, new String(msgBuffer, "UTF-8")); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + else + throw ex; + + } + } else { + message = new SIPResponse(); + try { + StatusLine sl = new StatusLineParser(firstLine + "\n").parse(); + ((SIPResponse) message).setStatusLine(sl); + } catch (ParseException ex) { + if (parseExceptionListener != null) { + try { + parseExceptionListener.handleException(ex, message, + StatusLine.class, firstLine, new String(msgBuffer, "UTF-8")); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } else + throw ex; + + } + } + return message; + } + + protected void processHeader(String header, SIPMessage message, ParseExceptionListener parseExceptionListener, byte[] rawMessage) throws ParseException { + if (header == null || header.length() == 0) + return; + + HeaderParser headerParser = null; + try { + headerParser = ParserFactory.createParser(header + "\n"); + } catch (ParseException ex) { + // https://java.net/jira/browse/JSIP-456 + if (parseExceptionListener != null) { + parseExceptionListener.handleException(ex, message, null, + header, null); + return; + } else { + throw ex; + } + } + + try { + SIPHeader sipHeader = headerParser.parse(); + message.attachHeader(sipHeader, false); + } catch (ParseException ex) { + if (parseExceptionListener != null) { + String headerName = Lexer.getHeaderName(header); + Class headerClass = NameMap.getClassFromName(headerName); + if (headerClass == null) { + headerClass = ExtensionHeaderImpl.class; + + } + try { + parseExceptionListener.handleException(ex, message, + headerClass, header, new String(rawMessage, "UTF-8")); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + + } + } + } + + /** + * Parse an address (nameaddr or address spec) and return and address + * structure. + * + * @param address + * is a String containing the address to be parsed. + * @return a parsed address structure. + * @since v1.0 + * @exception ParseException + * when the address is badly formatted. + */ + public AddressImpl parseAddress(String address) throws ParseException { + AddressParser addressParser = new AddressParser(address); + return addressParser.address(true); + } + + /** + * Parse a host:port and return a parsed structure. + * + * @param hostport + * is a String containing the host:port to be parsed + * @return a parsed address structure. + * @since v1.0 + * @exception throws + * a ParseException when the address is badly formatted. + * + public HostPort parseHostPort(String hostport) throws ParseException { + Lexer lexer = new Lexer("charLexer", hostport); + return new HostNameParser(lexer).hostPort(); + + } + */ + + /** + * Parse a host name and return a parsed structure. + * + * @param host + * is a String containing the host name to be parsed + * @return a parsed address structure. + * @since v1.0 + * @exception ParseException + * a ParseException when the hostname is badly formatted. + */ + public Host parseHost(String host) throws ParseException { + Lexer lexer = new Lexer("charLexer", host); + return new HostNameParser(lexer).host(); + + } + + /** + * Parse a telephone number return a parsed structure. + * + * @param telephone_number + * is a String containing the telephone # to be parsed + * @return a parsed address structure. + * @since v1.0 + * @exception ParseException + * a ParseException when the address is badly formatted. + */ + public TelephoneNumber parseTelephoneNumber(String telephone_number) + throws ParseException { + // Bug fix contributed by Will Scullin + return new URLParser(telephone_number).parseTelephoneNumber(true); + + } + + /** + * Parse a SIP url from a string and return a URI structure for it. + * + * @param url + * a String containing the URI structure to be parsed. + * @return A parsed URI structure + * @exception ParseException + * if there was an error parsing the message. + */ + + public SipUri parseSIPUrl(String url) throws ParseException { + try { + return new URLParser(url).sipURL(true); + } catch (ClassCastException ex) { + throw new ParseException(url + " Not a SIP URL ", 0); + } + } + + /** + * Parse a uri from a string and return a URI structure for it. + * + * @param url + * a String containing the URI structure to be parsed. + * @return A parsed URI structure + * @exception ParseException + * if there was an error parsing the message. + */ + + public GenericURI parseUrl(String url) throws ParseException { + return new URLParser(url).parse(); + } + + /** + * Parse an individual SIP message header from a string. + * + * @param header + * String containing the SIP header. + * @return a SIPHeader structure. + * @exception ParseException + * if there was an error parsing the message. + */ + public static SIPHeader parseSIPHeader(String header) throws ParseException { + int start = 0; + int end = header.length() - 1; + try { + // Squeeze out any leading control character. + while (header.charAt(start) <= 0x20) + start++; + + // Squeeze out any trailing control character. + while (header.charAt(end) <= 0x20) + end--; + } + catch (ArrayIndexOutOfBoundsException e) { + // Array contains only control char. + throw new ParseException("Empty header.", 0); + } + + StringBuilder buffer = new StringBuilder(end + 1); + int i = start; + int lineStart = start; + boolean endOfLine = false; + while (i <= end) { + char c = header.charAt(i); + if (c == '\r' || c == '\n') { + if (!endOfLine) { + buffer.append(header.substring(lineStart, i)); + endOfLine = true; + } + } + else { + if (endOfLine) { + endOfLine = false; + if (c == ' ' || c == '\t') { + buffer.append(' '); + lineStart = i + 1; + } + else { + lineStart = i; + } + } + } + + i++; + } + buffer.append(header.substring(lineStart, i)); + buffer.append('\n'); + + HeaderParser hp = ParserFactory.createParser(buffer.toString()); + if (hp == null) + throw new ParseException("could not create parser", 0); + return hp.parse(); + } + + /** + * Parse the SIP Request Line + * + * @param requestLine + * a String containing the request line to be parsed. + * @return a RequestLine structure that has the parsed RequestLine + * @exception ParseException + * if there was an error parsing the requestLine. + */ + + public RequestLine parseSIPRequestLine(String requestLine) + throws ParseException { + requestLine += "\n"; + return new RequestLineParser(requestLine).parse(); + } + + /** + * Parse the SIP Response message status line + * + * @param statusLine + * a String containing the Status line to be parsed. + * @return StatusLine class corresponding to message + * @exception ParseException + * if there was an error parsing + * @see StatusLine + */ + + public StatusLine parseSIPStatusLine(String statusLine) + throws ParseException { + statusLine += "\n"; + return new StatusLineParser(statusLine).parse(); + } + + public static void setComputeContentLengthFromMessage( + boolean computeContentLengthFromMessage) { + GBStringMsgParser.computeContentLengthFromMessage = computeContentLengthFromMessage; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/WvpSipDate.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbSipDate.java similarity index 97% rename from src/main/java/com/genersoft/iot/vmp/gb28181/bean/WvpSipDate.java rename to src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbSipDate.java index f2a256b9a..0631c5d06 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/WvpSipDate.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbSipDate.java @@ -8,7 +8,7 @@ import java.util.*; /** * 重写jain sip的SIPDate解决与国标时间格式不一致的问题 */ -public class WvpSipDate extends SIPDate { +public class GbSipDate extends SIPDate { /** * @@ -17,7 +17,7 @@ public class WvpSipDate extends SIPDate { private Calendar javaCal; - public WvpSipDate(long timeMillis) { + public GbSipDate(long timeMillis) { this.javaCal = new GregorianCalendar(TimeZone.getDefault(), Locale.getDefault()); Date date = new Date(timeMillis); this.javaCal.setTime(date); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbStringMsgParserFactory.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbStringMsgParserFactory.java new file mode 100644 index 000000000..3a9a1d196 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbStringMsgParserFactory.java @@ -0,0 +1,21 @@ +package com.genersoft.iot.vmp.gb28181.bean; + +import gov.nist.javax.sip.parser.MessageParser; +import gov.nist.javax.sip.parser.MessageParserFactory; +import gov.nist.javax.sip.stack.SIPTransactionStack; + +public class GbStringMsgParserFactory implements MessageParserFactory { + + /** + * msg parser is completely stateless, reuse isntance for the whole stack + * fixes https://github.com/RestComm/jain-sip/issues/92 + */ + private static GBStringMsgParser msgParser = new GBStringMsgParser(); + /* + * (non-Javadoc) + * @see gov.nist.javax.sip.parser.MessageParserFactory#createMessageParser(gov.nist.javax.sip.stack.SIPTransactionStack) + */ + public MessageParser createMessageParser(SIPTransactionStack stack) { + return msgParser; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java index e084f3523..ceeb3b17e 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java @@ -6,7 +6,7 @@ import com.genersoft.iot.vmp.gb28181.auth.DigestServerAuthenticationHelper; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo; import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo; -import com.genersoft.iot.vmp.gb28181.bean.WvpSipDate; +import com.genersoft.iot.vmp.gb28181.bean.GbSipDate; import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; @@ -145,8 +145,8 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen // 添加date头 SIPDateHeader dateHeader = new SIPDateHeader(); // 使用自己修改的 - WvpSipDate wvpSipDate = new WvpSipDate(Calendar.getInstance(Locale.ENGLISH).getTimeInMillis()); - dateHeader.setDate(wvpSipDate); + GbSipDate gbSipDate = new GbSipDate(Calendar.getInstance(Locale.ENGLISH).getTimeInMillis()); + dateHeader.setDate(gbSipDate); response.addHeader(dateHeader); if (request.getExpires() == null) { @@ -218,8 +218,8 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen // 添加date头 SIPDateHeader dateHeader = new SIPDateHeader(); // 使用自己修改的 - WvpSipDate wvpSipDate = new WvpSipDate(Calendar.getInstance(Locale.ENGLISH).getTimeInMillis()); - dateHeader.setDate(wvpSipDate); + GbSipDate gbSipDate = new GbSipDate(Calendar.getInstance(Locale.ENGLISH).getTimeInMillis()); + dateHeader.setDate(gbSipDate); response.addHeader(dateHeader); // 添加Contact头 diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java index 06dfb0063..b182b2653 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java @@ -470,7 +470,6 @@ public class DeviceQuery { public void getSnap(HttpServletResponse resp, @PathVariable String deviceId, @PathVariable String channelId, @RequestParam(required = false) String mark) { try { - final InputStream in = Files.newInputStream(new File("snap" + File.separator + deviceId + "_" + channelId + (mark == null? ".jpg": ("_" + mark + ".jpg"))).toPath()); resp.setContentType(MediaType.IMAGE_PNG_VALUE); IOUtils.copy(in, resp.getOutputStream()); From 885842249fb6b264b0abf78668872d04bdc179ce Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Fri, 7 Jul 2023 18:17:24 +0800 Subject: [PATCH 09/24] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=AC=AC=E4=B8=89?= =?UTF-8?q?=E6=96=B9=E5=AF=B9=E6=8E=A5=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/vmp/common/VideoManagerConstants.java | 1 + .../vmp/media/zlm/ZLMHttpHookListener.java | 26 ++++++- .../iot/vmp/vmanager/rtp/RtpController.java | 75 ++++++++++++++----- 3 files changed, 81 insertions(+), 21 deletions(-) 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 6eec845dc..ec25ea2e5 100644 --- a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java +++ b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java @@ -154,6 +154,7 @@ public class VideoManagerConstants { public static final String WVP_STREAM_GB_ID_PREFIX = "memberNo_"; public static final String WVP_STREAM_GPS_MSG_PREFIX = "WVP_STREAM_GPS_MSG_"; public static final String WVP_OTHER_SEND_RTP_INFO = "VMP_OTHER_SEND_RTP_INFO_"; + public static final String WVP_OTHER_RECEIVE_RTP_INFO = "VMP_OTHER_RECEIVE_RTP_INFO_"; /** * Redis Const 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 33c87138e..5df3be444 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.media.zlm; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; 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.*; @@ -22,14 +23,13 @@ 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.vmanager.bean.DeferredResultEx; -import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; -import com.genersoft.iot.vmp.vmanager.bean.StreamContent; -import com.genersoft.iot.vmp.vmanager.bean.WVPResult; +import com.genersoft.iot.vmp.utils.redis.RedisUtil; +import com.genersoft.iot.vmp.vmanager.bean.*; 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.util.ObjectUtils; import org.springframework.web.bind.annotation.*; @@ -106,6 +106,9 @@ public class ZLMHttpHookListener { @Autowired private AssistRESTfulUtils assistRESTfulUtils; + @Autowired + private RedisTemplate redisTemplate; + @Qualifier("taskExecutor") @Autowired private ThreadPoolTaskExecutor taskExecutor; @@ -255,6 +258,21 @@ public class ZLMHttpHookListener { result.setEnable_mp4(true); } } + + String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "*"; + // 将信息写入redis中,以备后用 + List scan = RedisUtil.scan(redisTemplate, receiveKey); + if (scan.size()>0) { + for (Object o : scan) { + String key = (String) o; + OtherRtpSendInfo otherRtpSendInfo = (OtherRtpSendInfo)redisTemplate.opsForValue().get(key); + if (otherRtpSendInfo != null && otherRtpSendInfo.getStream().equalsIgnoreCase(param.getStream())) { + result.setEnable_audio(true); + result.setEnable_mp4(true); + } + } + } + if (mediaInfo.getRecordAssistPort() > 0 && userSetting.getRecordPath() == null) { logger.info("推流时发现尚未设置录像路径,从assist服务中读取"); JSONObject info = assistRESTfulUtils.getInfo(mediaInfo, null); 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 311a007ae..c06c4af13 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 @@ -11,6 +11,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; 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.service.IDeviceChannelService; import com.genersoft.iot.vmp.service.IDeviceService; @@ -34,6 +35,7 @@ import org.springframework.web.bind.annotation.*; import java.io.IOException; import java.util.HashMap; import java.util.Map; +import java.util.UUID; @SuppressWarnings("rawtypes") @Tag(name = "第三方服务对接") @@ -120,12 +122,12 @@ public class RtpController { int localPort = zlmServerFactory.createRTPServer(mediaServerItem, stream, ssrcInt, null, false, tcpMode); // 注册回调如果rtp收流超时则通过回调发送通知 if (callBack != null) { - HookSubscribeForRtpServerTimeout hookSubscribeForRtpServerTimeout = HookSubscribeFactory.on_rtp_server_timeout(ssrc, null, mediaServerItem.getId()); + HookSubscribeForRtpServerTimeout hookSubscribeForRtpServerTimeout = HookSubscribeFactory.on_rtp_server_timeout(stream, String.valueOf(ssrcInt), mediaServerItem.getId()); // 订阅 zlm启动事件, 新的zlm也会从这里进入系统 hookSubscribe.addSubscribe(hookSubscribeForRtpServerTimeout, (mediaServerItemInUse, response)->{ if (stream.equals(response.getString("stream_id"))) { - logger.info("[开启收流和获取发流信息] 等待收流超时 callId->{}, 发送回调", callId); + logger.info("[第三方服务对接->开启收流和获取发流信息] 等待收流超时 callId->{}, 发送回调", callId); OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder(); OkHttpClient client = httpClientBuilder.build(); String url = callBack + "?callId=" + callId; @@ -133,7 +135,7 @@ public class RtpController { try { client.newCall(request).execute(); } catch (IOException e) { - logger.error("[开启收流和获取发流信息] 等待收流超时 callId->{}, 发送回调失败", callId, e); + logger.error("[第三方服务对接->开启收流和获取发流信息] 等待收流超时 callId->{}, 发送回调失败", callId, e); } } }); @@ -143,6 +145,9 @@ public class RtpController { otherRtpSendInfo.setReceivePort(localPort); otherRtpSendInfo.setCallId(callId); otherRtpSendInfo.setStream(stream); + String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + stream; + // 将信息写入redis中,以备后用 + redisTemplate.opsForValue().set(receiveKey, otherRtpSendInfo); if (isSend != null && isSend) { String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + callId; // 预创建发流信息 @@ -160,7 +165,7 @@ public class RtpController { }, 15000); otherRtpSendInfo.setIp(mediaServerItem.getSdpIp()); otherRtpSendInfo.setPort(port); - logger.info("[开启收流和获取发流信息] 结果,callId->{}, {}", callId, otherRtpSendInfo); + logger.info("[第三方服务对接->开启收流和获取发流信息] 结果,callId->{}, {}", callId, otherRtpSendInfo); } return otherRtpSendInfo; } @@ -173,6 +178,9 @@ public class RtpController { logger.info("[第三方服务对接->关闭收流] stream->{}", stream); MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer(); zlmServerFactory.closeRtpServer(mediaServerItem,stream); + String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + stream; + // 将信息写入redis中,以备后用 + redisTemplate.delete(receiveKey); } @GetMapping(value = "/send/start") @@ -187,9 +195,10 @@ public class RtpController { @Parameter(name = "onlyAudio", description = "是否只有音频", required = true) @Parameter(name = "isUdp", description = "是否为UDP", required = true) @Parameter(name = "streamType", description = "流类型,1为es流,2为ps流, 默认es流", required = false) - public void sendRTP(String ssrc, String ip, Integer port, String app, String stream, String callId, Boolean onlyAudio, Boolean isUdp, @RequestParam(required = false)Integer streamType) { - logger.info("[第三方服务对接->发送流] ssrc->{}, ip->{}, port->{}, app->{}, stream->{}, callId->{}, onlyAudio->{}, streamType->{}", - ssrc, ip, port, app, stream, callId, onlyAudio, streamType == 1? "ES":"PS"); + @Parameter(name = "pt", description = "rtp的pt", required = true) + public void sendRTP(String ssrc, String ip, Integer port, String app, String stream, String callId, Boolean onlyAudio, Boolean isUdp, @RequestParam(required = false)Integer streamType, Integer pt) { + logger.info("[第三方服务对接->发送流] ssrc->{}, ip->{}, port->{}, app->{}, stream->{}, callId->{}, onlyAudio->{}, streamType->{}, pt->{}", + ssrc, ip, port, app, stream, callId, onlyAudio, streamType == 1? "ES":"PS", pt); if (ObjectUtils.isEmpty(streamType)) { streamType = 1; } @@ -197,7 +206,7 @@ public class RtpController { String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + callId; OtherRtpSendInfo sendInfo = (OtherRtpSendInfo)redisTemplate.opsForValue().get(key); if (sendInfo != null) { - zlmServerFactory.releasePort(mediaServerItem, sendInfo.getCallId()); + zlmServerFactory.releasePort(mediaServerItem, callId); }else { sendInfo = new OtherRtpSendInfo(); } @@ -218,20 +227,52 @@ public class RtpController { param.put("src_port", sendInfo.getPort()); param.put("use_ps", streamType==2 ? "1" : "0"); param.put("only_audio", onlyAudio ? "1" : "0"); + param.put("pt", pt); - JSONObject jsonObject = zlmServerFactory.startSendRtpStream(mediaServerItem, param); - if (jsonObject.getInteger("code") == 0) { - logger.info("[第三方服务对接->发送流] 发流成功,callId->{}", callId); - redisTemplate.opsForValue().set(key, sendInfo); + dynamicTask.stop(key); + Boolean streamReady = zlmServerFactory.isStreamReady(mediaServerItem, app, stream); + if (streamReady) { + logger.info("[第三方服务对接->发送流] 流存在,开始发流,callId->{}", callId); + JSONObject jsonObject = zlmServerFactory.startSendRtpStream(mediaServerItem, param); + if (jsonObject.getInteger("code") == 0) { + logger.info("[第三方服务对接->发送流] 发流成功,callId->{}", callId); + redisTemplate.opsForValue().set(key, sendInfo); + }else { + redisTemplate.delete(key); + logger.info("[第三方服务对接->发送流] 发流失败,callId->{}, {}", callId, jsonObject.getString("msg")); + throw new ControllerException(ErrorCode.ERROR100.getCode(), "[发流失败] " + jsonObject.getString("msg")); + } }else { - redisTemplate.delete(key); - logger.info("[第三方服务对接->发送流] 发流失败,callId->{}, {}", callId, jsonObject.getString("msg")); - throw new ControllerException(ErrorCode.ERROR100.getCode(), "[发流失败] " + jsonObject.getString("msg")); + logger.info("[第三方服务对接->发送流] 流不存在,等待流上线,callId->{}", callId); + String uuid = UUID.randomUUID().toString(); + HookSubscribeForStreamChange hookSubscribeForStreamChange = HookSubscribeFactory.on_stream_changed(app, stream, true, "rtsp", mediaServerItem.getId()); + dynamicTask.startDelay(uuid, ()->{ + logger.info("[第三方服务对接->发送流] 等待流上线超时 callId->{}", callId); + redisTemplate.delete(key); + hookSubscribe.removeSubscribe(hookSubscribeForStreamChange); + }, 10000); + + // 订阅 zlm启动事件, 新的zlm也会从这里进入系统 + OtherRtpSendInfo finalSendInfo = sendInfo; + hookSubscribe.addSubscribe(hookSubscribeForStreamChange, + (mediaServerItemInUse, response)->{ + dynamicTask.stop(uuid); + logger.info("[第三方服务对接->发送流] 流上线,开始发流 callId->{}", callId); + JSONObject jsonObject = zlmServerFactory.startSendRtpStream(mediaServerItem, param); + System.out.println("========发流结果=========="); + System.out.println(jsonObject); + if (jsonObject.getInteger("code") == 0) { + logger.info("[第三方服务对接->发送流] 发流成功,callId->{}", callId); + redisTemplate.opsForValue().set(key, finalSendInfo); + }else { + redisTemplate.delete(key); + logger.info("[第三方服务对接->发送流] 发流失败,callId->{}, {}", callId, jsonObject.getString("msg")); + throw new ControllerException(ErrorCode.ERROR100.getCode(), "[发流失败] " + jsonObject.getString("msg")); + } + }); } } - - @GetMapping(value = "/send/stop") @ResponseBody @Operation(summary = "关闭发送流") From 468e2b2ffbbb4e15dea11d1f9c7451a8097a3ab8 Mon Sep 17 00:00:00 2001 From: xiaoQQya Date: Sun, 9 Jul 2023 20:22:40 +0800 Subject: [PATCH 10/24] =?UTF-8?q?fix(play):=20=E4=BF=AE=E5=A4=8D=E4=BD=9C?= =?UTF-8?q?=E4=B8=BA=E4=B8=8A=E7=BA=A7=E5=B9=B3=E5=8F=B0=E7=82=B9=E6=92=AD?= =?UTF-8?q?=E6=88=AA=E5=8F=96=E5=BF=AB=E7=85=A7=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/vmp/service/impl/PlayServiceImpl.java | 36 ++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-) 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 519013920..a7c70cb76 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 @@ -271,18 +271,7 @@ public class PlayServiceImpl implements IPlayService { streamInfo); logger.info("[点播成功] deviceId: {}, channelId:{}, 码流类型:{}", device.getDeviceId(), device.isSwitchPrimarySubStream() ? "辅码流" : "主码流"); - String streamUrl; - if (mediaServerItemInuse.getRtspPort() != 0) { - streamUrl = String.format("rtsp://127.0.0.1:%s/%s/%s", mediaServerItemInuse.getRtspPort(), "rtp", ssrcInfo.getStream()); - }else { - streamUrl = String.format("http://127.0.0.1:%s/%s/%s.live.mp4", mediaServerItemInuse.getHttpPort(), "rtp", ssrcInfo.getStream()); - } - String path = "snap"; - String fileName = device.getDeviceId() + "_" + channelId + ".jpg"; - // 请求截图 - logger.info("[请求截图]: " + fileName); - zlmresTfulUtils.getSnap(mediaServerItemInuse, streamUrl, 15, 1, path, fileName); - + snapOnPlay(mediaServerItemInuse, device.getDeviceId(), channelId, ssrcInfo.getStream()); }, (event) -> { inviteInfo.setStatus(InviteSessionStatus.ok); @@ -365,6 +354,7 @@ public class PlayServiceImpl implements IPlayService { InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo); + snapOnPlay(mediaServerItemInUse, device.getDeviceId(), channelId, stream); }); return; } @@ -440,6 +430,28 @@ public class PlayServiceImpl implements IPlayService { } } + /** + * 点播成功时调用截图. + * + * @param mediaServerItemInuse media + * @param deviceId 设备 ID + * @param channelId 通道 ID + * @param stream ssrc + */ + private void snapOnPlay(MediaServerItem 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); + } else { + streamUrl = String.format("http://127.0.0.1:%s/%s/%s.live.mp4", mediaServerItemInuse.getHttpPort(), "rtp", stream); + } + String path = "snap"; + String fileName = deviceId + "_" + channelId + ".jpg"; + // 请求截图 + logger.info("[请求截图]: " + fileName); + zlmresTfulUtils.getSnap(mediaServerItemInuse, streamUrl, 15, 1, path, fileName); + } + private StreamInfo onPublishHandlerForPlay(MediaServerItem mediaServerItem, HookParam hookParam, String deviceId, String channelId) { StreamInfo streamInfo = null; Device device = redisCatchStorage.getDevice(deviceId); From 04e7f48fde1b1a653d413eb41186ec7354f5ae31 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Mon, 10 Jul 2023 14:30:59 +0800 Subject: [PATCH 11/24] =?UTF-8?q?=E5=90=88=E5=B9=B6=E4=B8=BB=E7=BA=BF?= =?UTF-8?q?=E7=9A=84=E5=8F=91=E6=B5=81=E7=AB=AF=E5=8F=A3=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/2.6.8补丁更新.sql | 2 + .../genersoft/iot/vmp/conf/MediaConfig.java | 11 ++ .../request/impl/AckRequestProcessor.java | 10 +- .../request/impl/InviteRequestProcessor.java | 16 +-- .../iot/vmp/media/zlm/SendRtpPortManager.java | 55 ++++++++ .../vmp/media/zlm/ZLMHttpHookListener.java | 30 ++-- .../vmp/media/zlm/ZLMRTPServerFactory.java | 130 ++---------------- .../media/zlm/dto/MediaSendRtpPortInfo.java | 50 +++++++ .../vmp/media/zlm/dto/MediaServerItem.java | 11 ++ .../zlm/dto/hook/HookResultForOnPublish.java | 10 ++ .../service/impl/MediaServerServiceImpl.java | 38 ++++- .../redisMsg/RedisGbPlayMsgListener.java | 4 +- .../vmp/storager/dao/MediaServerMapper.java | 4 + .../vmp/vmanager/bean/OtherRtpSendInfo.java | 2 +- .../iot/vmp/vmanager/rtp/RtpController.java | 55 ++------ .../src/components/dialog/MediaServerEdit.vue | 21 ++- 16 files changed, 234 insertions(+), 215 deletions(-) create mode 100644 sql/2.6.8补丁更新.sql create mode 100644 src/main/java/com/genersoft/iot/vmp/media/zlm/SendRtpPortManager.java create mode 100644 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaSendRtpPortInfo.java diff --git a/sql/2.6.8补丁更新.sql b/sql/2.6.8补丁更新.sql new file mode 100644 index 000000000..8ce9d543d --- /dev/null +++ b/sql/2.6.8补丁更新.sql @@ -0,0 +1,2 @@ +alter table media_server + add sendRtpPortRange varchar(50) not null; \ No newline at end of file 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 fa126794d..cd228803b 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java @@ -75,6 +75,9 @@ public class MediaConfig{ @Value("${media.rtp.port-range}") private String rtpPortRange; + @Value("${media.rtp.send-port-range}") + private String rtpSendPortRange; + @Value("${media.record-assist-port:0}") private Integer recordAssistPort = 0; @@ -206,6 +209,7 @@ public class MediaConfig{ mediaServerItem.setSecret(secret); mediaServerItem.setRtpEnable(rtpEnable); mediaServerItem.setRtpPortRange(rtpPortRange); + mediaServerItem.setSendRtpPortRange(rtpSendPortRange); mediaServerItem.setRecordAssistPort(recordAssistPort); mediaServerItem.setHookAliveInterval(30.00f); @@ -222,4 +226,11 @@ public class MediaConfig{ return false; } + public String getRtpSendPortRange() { + return rtpSendPortRange; + } + + public void setRtpSendPortRange(String rtpSendPortRange) { + this.rtpSendPortRange = rtpSendPortRange; + } } 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 f40e0c876..e7091fbc7 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 @@ -140,15 +140,7 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, jsonObject, param, callIdHeader); }); }else { - // 如果是非严格模式,需要关闭端口占用 - JSONObject startSendRtpStreamResult = null; - if (sendRtpItem.getLocalPort() != 0) { - if (zlmrtpServerFactory.releasePort(mediaInfo, sendRtpItem.getSsrc())) { - startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); - } - }else { - startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); - } + JSONObject startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); if (startSendRtpStreamResult != null) { startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, startSendRtpStreamResult, param, callIdHeader); } 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 b7f600f7f..073720aa8 100644 --- 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 @@ -349,9 +349,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements } logger.info("[上级Invite] {}, 平台:{}, 通道:{}, 收流地址:{}:{},收流方式:{}, ssrc:{}", sessionName, username, channelId, addressStr, port, streamTypeStr, ssrc); SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, - device.getDeviceId(), channelId, mediaTransmissionTCP, platform.isRtcp(), ssrcFromCallback -> { - return redisCatchStorage.querySendRTPServer(platform.getServerGBId(), channelId, null, callIdHeader.getCallId()) != null; - }); + device.getDeviceId(), channelId, mediaTransmissionTCP, platform.isRtcp()); if (tcpActive != null) { sendRtpItem.setTcpActive(tcpActive); @@ -553,9 +551,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements if (streamReady) { // 自平台内容 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, - gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp(), ssrcFromCallback ->{ - return redisCatchStorage.querySendRTPServer(platform.getServerGBId(), channelId, null, callIdHeader.getCallId()) != null; - }); + gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp()); if (sendRtpItem == null) { logger.warn("服务器端口资源不足"); @@ -594,9 +590,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements if (streamReady) { // 自平台内容 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, - gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp(), ssrcFromCallback ->{ - return redisCatchStorage.querySendRTPServer(platform.getServerGBId(), channelId, null, callIdHeader.getCallId()) != null; - }); + gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp()); if (sendRtpItem == null) { logger.warn("服务器端口资源不足"); @@ -713,9 +707,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements dynamicTask.stop(callIdHeader.getCallId()); if (serverId.equals(userSetting.getServerId())) { SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, finalPort, ssrc, requesterId, - app, stream, channelId, mediaTransmissionTCP, platform.isRtcp(), ssrcFromCallback -> { - return redisCatchStorage.querySendRTPServer(platform.getServerGBId(), channelId, null, callIdHeader.getCallId()) != null; - }); + app, stream, channelId, mediaTransmissionTCP, platform.isRtcp()); if (sendRtpItem == null) { logger.warn("上级点时创建sendRTPItem失败,可能是服务器端口资源不足"); 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 new file mode 100644 index 000000000..8366a4a2d --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/SendRtpPortManager.java @@ -0,0 +1,55 @@ +package com.genersoft.iot.vmp.media.zlm; + +import com.genersoft.iot.vmp.conf.UserSetting; +import com.genersoft.iot.vmp.media.zlm.dto.MediaSendRtpPortInfo; +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.Component; + +@Component +public class SendRtpPortManager { + + private final static Logger logger = LoggerFactory.getLogger(SendRtpPortManager.class); + + @Autowired + private UserSetting userSetting; + + @Autowired + private RedisTemplate redisTemplate; + + private final String KEY = "VM_MEDIA_SEND_RTP_PORT_RANGE_"; + + + 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 key = KEY + userSetting.getServerId() + "_" + mediaServerId; + MediaSendRtpPortInfo mediaSendRtpPortInfo = (MediaSendRtpPortInfo)redisTemplate.opsForValue().get(key); + if (mediaSendRtpPortInfo == null) { + logger.warn("[发送端口管理] 获取{}的发送端口时未找到端口信息", mediaSendRtpPortInfo); + return 0; + } + int port; + if (mediaSendRtpPortInfo.getCurrent() %2 != 0) { + port = mediaSendRtpPortInfo.getCurrent() + 1; + }else { + port = mediaSendRtpPortInfo.getCurrent() + 2; + } + if (port > mediaSendRtpPortInfo.getEnd()) { + if (mediaSendRtpPortInfo.getStart() %2 != 0) { + port = mediaSendRtpPortInfo.getStart() + 1; + }else { + port = mediaSendRtpPortInfo.getStart(); + } + } + mediaSendRtpPortInfo.setCurrent(port); + redisTemplate.opsForValue().set(key, mediaSendRtpPortInfo); + return port; + } +} 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 5df3be444..d23c6c7e5 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java @@ -23,7 +23,6 @@ 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.redis.RedisUtil; import com.genersoft.iot.vmp.vmanager.bean.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -223,9 +222,6 @@ public class ZLMHttpHookListener { HookResultForOnPublish result = HookResultForOnPublish.SUCCESS(); - if (!"rtp".equals(param.getApp())) { - result.setEnable_audio(true); - } taskExecutor.execute(() -> { ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_publish, json); @@ -259,20 +255,6 @@ public class ZLMHttpHookListener { } } - String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "*"; - // 将信息写入redis中,以备后用 - List scan = RedisUtil.scan(redisTemplate, receiveKey); - if (scan.size()>0) { - for (Object o : scan) { - String key = (String) o; - OtherRtpSendInfo otherRtpSendInfo = (OtherRtpSendInfo)redisTemplate.opsForValue().get(key); - if (otherRtpSendInfo != null && otherRtpSendInfo.getStream().equalsIgnoreCase(param.getStream())) { - result.setEnable_audio(true); - result.setEnable_mp4(true); - } - } - } - if (mediaInfo.getRecordAssistPort() > 0 && userSetting.getRecordPath() == null) { logger.info("推流时发现尚未设置录像路径,从assist服务中读取"); JSONObject info = assistRESTfulUtils.getInfo(mediaInfo, null); @@ -291,6 +273,18 @@ public class ZLMHttpHookListener { } } } + if (param.getApp().equalsIgnoreCase("rtp")) { + String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_" + param.getStream(); + System.out.println(receiveKey); + OtherRtpSendInfo otherRtpSendInfo = (OtherRtpSendInfo)redisTemplate.opsForValue().get(receiveKey); + System.out.println("otherRtpSendInfo != null ====>" + (otherRtpSendInfo != null)); + if (otherRtpSendInfo != null) { + System.out.println("otherRtpSendInfo != null"); + result.setEnable_audio(true); + result.setEnable_mp4(true); + } + } + logger.info("[ZLM HOOK]推流鉴权 响应:{}->{}->>>>{}", param.getMediaServerId(), param, result); return result; } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java index 9c5a47282..af4b3918a 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java @@ -1,20 +1,18 @@ 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.conf.UserSetting; import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; -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.MediaServerItem; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import java.util.*; +import java.util.HashMap; +import java.util.Map; @Component public class ZLMRTPServerFactory { @@ -30,68 +28,8 @@ public class ZLMRTPServerFactory { @Autowired private ZlmHttpHookSubscribe hookSubscribe; - private int[] portRangeArray = new int[2]; - - public int getFreePort(MediaServerItem mediaServerItem, int startPort, int endPort, List usedFreelist) { - if (endPort <= startPort) { - return -1; - } - if (usedFreelist == null) { - usedFreelist = new ArrayList<>(); - } - JSONObject listRtpServerJsonResult = zlmresTfulUtils.listRtpServer(mediaServerItem); - if (listRtpServerJsonResult != null) { - JSONArray data = listRtpServerJsonResult.getJSONArray("data"); - if (data != null) { - for (int i = 0; i < data.size(); i++) { - JSONObject dataItem = data.getJSONObject(i); - usedFreelist.add(dataItem.getInteger("port")); - } - } - } - - Map param = new HashMap<>(); - int result = -1; - // 设置推流端口 - if (startPort%2 == 1) { - startPort ++; - } - boolean checkPort = false; - for (int i = startPort; i < endPort + 1; i+=2) { - if (!usedFreelist.contains(i)){ - checkPort = true; - startPort = i; - break; - } - } - if (!checkPort) { - logger.warn("未找到节点{}上范围[{}-{}]的空闲端口", mediaServerItem.getId(), startPort, endPort); - return -1; - } - param.put("port", startPort); - String stream = UUID.randomUUID().toString(); - param.put("enable_tcp", 1); - param.put("stream_id", stream); -// param.put("port", 0); - JSONObject openRtpServerResultJson = zlmresTfulUtils.openRtpServer(mediaServerItem, param); - - if (openRtpServerResultJson != null) { - if (openRtpServerResultJson.getInteger("code") == 0) { - result= openRtpServerResultJson.getInteger("port"); - Map closeRtpServerParam = new HashMap<>(); - closeRtpServerParam.put("stream_id", stream); - zlmresTfulUtils.closeRtpServer(mediaServerItem, closeRtpServerParam); - }else { - usedFreelist.add(startPort); - startPort +=2; - result = getFreePort(mediaServerItem, startPort, endPort,usedFreelist); - } - }else { - // 检查ZLM状态 - logger.error("创建RTP Server 失败 {}: 请检查ZLM服务", param.get("port")); - } - return result; - } + @Autowired + private SendRtpPortManager sendRtpPortManager; /** * 开启rtpServer @@ -220,13 +158,13 @@ public class ZLMRTPServerFactory { * @return SendRtpItem */ public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, - String deviceId, String channelId, boolean tcp, boolean rtcp, KeepPortCallback callback){ + String deviceId, String channelId, boolean tcp, boolean rtcp){ // 默认为随机端口 int localPort = 0; if (userSetting.getGbSendStreamStrict()) { if (userSetting.getGbSendStreamStrict()) { - localPort = keepPort(serverItem, ssrc, localPort, callback); + localPort = sendRtpPortManager.getNextPort(serverItem.getId()); if (localPort == 0) { return null; } @@ -259,11 +197,11 @@ public class ZLMRTPServerFactory { * @return SendRtpItem */ public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, - String app, String stream, String channelId, boolean tcp, boolean rtcp, KeepPortCallback callback){ + String app, String stream, String channelId, boolean tcp, boolean rtcp){ // 默认为随机端口 int localPort = 0; if (userSetting.getGbSendStreamStrict()) { - localPort = keepPort(serverItem, ssrc, localPort, callback); + localPort = sendRtpPortManager.getNextPort(serverItem.getId()); if (localPort == 0) { return null; } @@ -284,58 +222,6 @@ public class ZLMRTPServerFactory { return sendRtpItem; } - public interface KeepPortCallback{ - Boolean keep(String ssrc); - } - - /** - * 保持端口,直到需要需要发流时再释放 - */ - public int keepPort(MediaServerItem serverItem, String ssrc, int localPort, KeepPortCallback keepPortCallback) { - Map param = new HashMap<>(3); - param.put("port", localPort); - param.put("enable_tcp", 1); - param.put("stream_id", ssrc); - JSONObject jsonObject = zlmresTfulUtils.openRtpServer(serverItem, param); - if (jsonObject.getInteger("code") == 0) { - localPort = jsonObject.getInteger("port"); - HookSubscribeForRtpServerTimeout hookSubscribeForRtpServerTimeout = HookSubscribeFactory.on_rtp_server_timeout(ssrc, null, serverItem.getId()); - // 订阅 zlm启动事件, 新的zlm也会从这里进入系统 - Integer finalLocalPort = localPort; - hookSubscribe.addSubscribe(hookSubscribeForRtpServerTimeout, - (MediaServerItem mediaServerItem, JSONObject response)->{ - System.out.println("监听端口到期继续保持监听"); - System.out.println(response); - if (ssrc.equals(response.getString("stream_id"))) { - if (keepPortCallback.keep(ssrc)) { - logger.info("[上级点播] {}->监听端口到期继续保持监听", ssrc); - keepPort(serverItem, ssrc, finalLocalPort, keepPortCallback); - }else { - logger.info("[上级点播] {}->发送取消,无需继续监听", ssrc); - releasePort(serverItem, ssrc); - } - } - - }); - logger.info("[上级点播] {}->监听端口: {}", ssrc, localPort); - }else { - logger.info("[上级点播] 监听端口失败: {}", ssrc); - } - return localPort; - } - - /** - * 释放保持的端口 - */ - public boolean releasePort(MediaServerItem serverItem, String ssrc) { - logger.info("[上级点播] {}->释放监听端口", ssrc); - boolean closeRTPServerResult = closeRtpServer(serverItem, ssrc); - HookSubscribeForRtpServerTimeout hookSubscribeForRtpServerTimeout = HookSubscribeFactory.on_rtp_server_timeout(ssrc, null, serverItem.getId()); - // 订阅 zlm启动事件, 新的zlm也会从这里进入系统 - hookSubscribe.removeSubscribe(hookSubscribeForRtpServerTimeout); - return closeRTPServerResult; - } - /** * 调用zlm RESTFUL API —— startSendRtp */ 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 new file mode 100644 index 000000000..2e9f63176 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaSendRtpPortInfo.java @@ -0,0 +1,50 @@ +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/media/zlm/dto/MediaServerItem.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java index e6bbb5fac..066a67762 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java @@ -62,6 +62,9 @@ public class MediaServerItem{ @Schema(description = "多端口RTP收流端口范围") private String rtpPortRange; + @Schema(description = "RTP发流端口范围") + private String sendRtpPortRange; + @Schema(description = "assist服务端口") private int recordAssistPort; @@ -297,4 +300,12 @@ public class MediaServerItem{ public void setHookAliveInterval(Float hookAliveInterval) { this.hookAliveInterval = hookAliveInterval; } + + public String getSendRtpPortRange() { + return sendRtpPortRange; + } + + public void setSendRtpPortRange(String sendRtpPortRange) { + this.sendRtpPortRange = sendRtpPortRange; + } } 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 cb8e73839..68d969f41 100644 --- 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 @@ -50,4 +50,14 @@ public class HookResultForOnPublish extends HookResult{ public void setMp4_save_path(String mp4_save_path) { this.mp4_save_path = mp4_save_path; } + + @Override + public String toString() { + return "HookResultForOnPublish{" + + "enable_audio=" + enable_audio + + ", enable_mp4=" + enable_mp4 + + ", mp4_max_second=" + mp4_max_second + + ", mp4_save_path='" + mp4_save_path + '\'' + + '}'; + } } 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 eaa6a9fb9..789974b8e 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 @@ -11,10 +11,7 @@ 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.AssistRESTfulUtils; -import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; -import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; -import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; +import com.genersoft.iot.vmp.media.zlm.*; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.ServerKeepaliveData; import com.genersoft.iot.vmp.service.IMediaServerService; @@ -69,6 +66,10 @@ public class MediaServerServiceImpl implements IMediaServerService { @Autowired private UserSetting userSetting; + @Autowired + private SendRtpPortManager sendRtpPortManager; + + @Autowired private AssistRESTfulUtils assistRESTfulUtils; @@ -115,13 +116,40 @@ 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); if (hasKey != null && ! hasKey) { redisTemplate.opsForValue().set(key, mediaServerItem); } - } } 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 8231fb339..33eb5c1fd 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java @@ -317,9 +317,7 @@ public class RedisGbPlayMsgListener implements MessageListener { SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, content.getIp(), content.getPort(), content.getSsrc(), content.getPlatformId(), content.getApp(), content.getStream(), content.getChannelId(), - content.getTcp(), content.getRtcp(), ssrcFromCallback -> { - return querySendRTPServer(content.getPlatformId(), content.getChannelId(), content.getStream(), null) != null; - }); + content.getTcp(), content.getRtcp()); WVPResult result = new WVPResult<>(); result.setCode(0); 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 97e74ae84..e222ba865 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java @@ -28,6 +28,7 @@ public interface MediaServerMapper { "secret, " + "rtpEnable, " + "rtpPortRange, " + + "sendRtpPortRange, " + "recordAssistPort, " + "defaultServer, " + "createTime, " + @@ -51,6 +52,7 @@ public interface MediaServerMapper { "#{secret}, " + "#{rtpEnable}, " + "#{rtpPortRange}, " + + "#{sendRtpPortRange}, " + "#{recordAssistPort}, " + "#{defaultServer}, " + "#{createTime}, " + @@ -75,6 +77,7 @@ public interface MediaServerMapper { ", autoConfig=#{autoConfig}" + ", rtpEnable=#{rtpEnable}" + ", rtpPortRange=#{rtpPortRange}" + + ", sendRtpPortRange=#{sendRtpPortRange}" + ", secret=#{secret}" + ", recordAssistPort=#{recordAssistPort}" + ", hookAliveInterval=#{hookAliveInterval}" + @@ -98,6 +101,7 @@ public interface MediaServerMapper { ", autoConfig=#{autoConfig}" + ", rtpEnable=#{rtpEnable}" + ", rtpPortRange=#{rtpPortRange}" + + ", sendRtpPortRange=#{sendRtpPortRange}" + ", secret=#{secret}" + ", recordAssistPort=#{recordAssistPort}" + ", hookAliveInterval=#{hookAliveInterval}" + diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/bean/OtherRtpSendInfo.java b/src/main/java/com/genersoft/iot/vmp/vmanager/bean/OtherRtpSendInfo.java index 225e40c4f..9fea5c543 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/bean/OtherRtpSendInfo.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/bean/OtherRtpSendInfo.java @@ -124,7 +124,7 @@ public class OtherRtpSendInfo { @Override public String toString() { return "OtherRtpSendInfo{" + - "ip='" + ip + '\'' + + " ip='" + ip + '\'' + ", port=" + port + ", receiveIp='" + receiveIp + '\'' + ", receivePort=" + receivePort + 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 c06c4af13..ad021ba49 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 @@ -3,20 +3,16 @@ package com.genersoft.iot.vmp.vmanager.rtp; import com.alibaba.fastjson2.JSONObject; 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.VersionInfo; import com.genersoft.iot.vmp.conf.exception.ControllerException; +import com.genersoft.iot.vmp.media.zlm.SendRtpPortManager; import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; 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.service.IDeviceChannelService; -import com.genersoft.iot.vmp.service.IDeviceService; import com.genersoft.iot.vmp.service.IMediaServerService; -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import com.genersoft.iot.vmp.vmanager.bean.OtherRtpSendInfo; import io.swagger.v3.oas.annotations.Operation; @@ -27,7 +23,6 @@ import okhttp3.Request; 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.data.redis.core.RedisTemplate; import org.springframework.util.ObjectUtils; import org.springframework.web.bind.annotation.*; @@ -36,6 +31,7 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.UUID; +import java.util.concurrent.TimeUnit; @SuppressWarnings("rawtypes") @Tag(name = "第三方服务对接") @@ -56,20 +52,11 @@ public class RtpController { private IMediaServerService mediaServerService; @Autowired - private VersionInfo versionInfo; - - @Autowired - private SipConfig sipConfig; + private SendRtpPortManager sendRtpPortManager; @Autowired private UserSetting userSetting; - @Autowired - private IDeviceService deviceService; - - @Autowired - private IDeviceChannelService channelService; - @Autowired private DynamicTask dynamicTask; @@ -78,14 +65,6 @@ public class RtpController { private RedisTemplate redisTemplate; - @Value("${server.port}") - private int serverPort; - - - @Autowired - private IRedisCatchStorage redisCatchStorage; - - @GetMapping(value = "/receive/open") @ResponseBody @Operation(summary = "开启收流和获取发流信息") @@ -145,24 +124,15 @@ public class RtpController { otherRtpSendInfo.setReceivePort(localPort); otherRtpSendInfo.setCallId(callId); otherRtpSendInfo.setStream(stream); - String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + stream; + String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_" + stream; // 将信息写入redis中,以备后用 redisTemplate.opsForValue().set(receiveKey, otherRtpSendInfo); if (isSend != null && isSend) { - String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + callId; + String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + "_" + callId; // 预创建发流信息 - int port = zlmServerFactory.keepPort(mediaServerItem, callId, 0, ssrc1 -> { - return redisTemplate.opsForValue().get(key) != null; - }); - + int port = sendRtpPortManager.getNextPort(mediaServerItem.getId()); // 将信息写入redis中,以备后用 - redisTemplate.opsForValue().set(key, otherRtpSendInfo); - // 设置超时任务,超时未使用,则自动移除,并关闭端口保持, 默认五分钟 - dynamicTask.startDelay(key, ()->{ - logger.info("[第三方服务对接->开启收流和获取发流信息] 端口保持超时 callId->{}", callId); - redisTemplate.delete(key); - zlmServerFactory.releasePort(mediaServerItem, callId); - }, 15000); + redisTemplate.opsForValue().set(key, otherRtpSendInfo, 300, TimeUnit.SECONDS); otherRtpSendInfo.setIp(mediaServerItem.getSdpIp()); otherRtpSendInfo.setPort(port); logger.info("[第三方服务对接->开启收流和获取发流信息] 结果,callId->{}, {}", callId, otherRtpSendInfo); @@ -178,7 +148,7 @@ public class RtpController { logger.info("[第三方服务对接->关闭收流] stream->{}", stream); MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer(); zlmServerFactory.closeRtpServer(mediaServerItem,stream); - String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + stream; + String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_" + stream; // 将信息写入redis中,以备后用 redisTemplate.delete(receiveKey); } @@ -203,11 +173,9 @@ public class RtpController { streamType = 1; } MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer(); - String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + callId; + String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + "_" + callId; OtherRtpSendInfo sendInfo = (OtherRtpSendInfo)redisTemplate.opsForValue().get(key); - if (sendInfo != null) { - zlmServerFactory.releasePort(mediaServerItem, callId); - }else { + if (sendInfo == null) { sendInfo = new OtherRtpSendInfo(); } sendInfo.setPushApp(app); @@ -229,7 +197,6 @@ public class RtpController { param.put("only_audio", onlyAudio ? "1" : "0"); param.put("pt", pt); - dynamicTask.stop(key); Boolean streamReady = zlmServerFactory.isStreamReady(mediaServerItem, app, stream); if (streamReady) { logger.info("[第三方服务对接->发送流] 流存在,开始发流,callId->{}", callId); @@ -279,7 +246,7 @@ public class RtpController { @Parameter(name = "callId", description = "整个过程的唯一标识,不传则使用随机端口发流", required = true) public void closeSendRTP(String callId) { logger.info("[第三方服务对接->关闭发送流] callId->{}", callId); - String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + callId; + String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + "_" + callId; OtherRtpSendInfo sendInfo = (OtherRtpSendInfo)redisTemplate.opsForValue().get(key); if (sendInfo == null){ throw new ControllerException(ErrorCode.ERROR100.getCode(), "未开启发流"); diff --git a/web_src/src/components/dialog/MediaServerEdit.vue b/web_src/src/components/dialog/MediaServerEdit.vue index 15923c1f8..bb55048c9 100644 --- a/web_src/src/components/dialog/MediaServerEdit.vue +++ b/web_src/src/components/dialog/MediaServerEdit.vue @@ -89,6 +89,11 @@ - + + + - + + @@ -172,6 +177,7 @@ export default { rtmpSSlPort: "", rtpEnable: false, rtpPortRange: "", + sendRtpPortRange: "", rtpProxyPort: "", rtspPort: "", rtspSSLPort: "", @@ -179,6 +185,9 @@ export default { rtpPortRange1:30000, rtpPortRange2:30500, + sendRtpPortRange1:50000, + sendRtpPortRange2:60000, + rules: { ip: [{ required: true, validator: isValidIp, message: '请输入有效的IP地址', trigger: 'blur' }], httpPort: [{ required: true, validator: isValidPort, message: '请输入有效的端口号', trigger: 'blur' }], @@ -214,10 +223,15 @@ export default { this.currentStep = 3; if (param.rtpPortRange) { let rtpPortRange = this.mediaServerForm.rtpPortRange.split(","); + let sendRtpPortRange = this.mediaServerForm.sendRtpPortRange.split(","); if (rtpPortRange.length > 0) { this.rtpPortRange1 = rtpPortRange[0] this.rtpPortRange2 = rtpPortRange[1] } + if (sendRtpPortRange.length > 0) { + this.sendRtpPortRange1 = sendRtpPortRange[0] + this.sendRtpPortRange2 = sendRtpPortRange[1] + } } } }, @@ -240,6 +254,8 @@ export default { that.mediaServerForm.autoConfig = true; that.rtpPortRange1 = 30000 that.rtpPortRange2 = 30500 + that.sendRtpPortRange1 = 50000 + that.sendRtpPortRange2 = 60000 that.serverCheck = 1; }else { that.serverCheck = -1; @@ -321,12 +337,15 @@ export default { rtmpSSlPort: "", rtpEnable: false, rtpPortRange: "", + sendRtpPortRange: "", rtpProxyPort: "", rtspPort: "", rtspSSLPort: "", }; this.rtpPortRange1 = 30500; this.rtpPortRange2 = 30500; + this.sendRtpPortRange1 = 50000; + this.sendRtpPortRange2 = 60000; this.listChangeCallback = null this.currentStep = 1; }, @@ -351,7 +370,7 @@ export default { portRangeChange: function() { if (this.mediaServerForm.rtpEnable) { this.mediaServerForm.rtpPortRange = this.rtpPortRange1 + "," + this.rtpPortRange2 - console.log(this.mediaServerForm.rtpPortRange) + this.mediaServerForm.sendRtpPortRange = this.sendRtpPortRange1 + "," + this.sendRtpPortRange2 } } }, From f525b5572988326c4b73da9f68e7ee7e292a2e46 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Wed, 12 Jul 2023 15:13:53 +0800 Subject: [PATCH 12/24] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=8F=91=E6=B5=81?= =?UTF-8?q?=E5=A4=8D=E7=9B=96=E7=9A=84=E4=B8=BA=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vmp/media/zlm/ZLMRTPServerFactory.java | 5 ++++- .../iot/vmp/vmanager/rtp/RtpController.java | 20 ++++++++++++++----- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java index af4b3918a..82a0faf4e 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java @@ -85,7 +85,10 @@ public class ZLMRTPServerFactory { }else { param.put("port", port); } - param.put("ssrc", ssrc); + if (ssrc != 0) { + param.put("ssrc", ssrc); + } + JSONObject openRtpServerResultJson = zlmresTfulUtils.openRtpServer(mediaServerItem, param); logger.info(JSONObject.toJSONString(openRtpServerResultJson)); if (openRtpServerResultJson != null) { 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 ad021ba49..b7a7e1524 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 @@ -13,6 +13,7 @@ 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.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; import io.swagger.v3.oas.annotations.Operation; @@ -29,6 +30,7 @@ import org.springframework.web.bind.annotation.*; import java.io.IOException; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.TimeUnit; @@ -98,6 +100,7 @@ public class RtpController { } } + String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_" + callId + "_" + stream; int localPort = zlmServerFactory.createRTPServer(mediaServerItem, stream, ssrcInt, null, false, tcpMode); // 注册回调如果rtp收流超时则通过回调发送通知 if (callBack != null) { @@ -107,6 +110,8 @@ public class RtpController { (mediaServerItemInUse, response)->{ if (stream.equals(response.getString("stream_id"))) { logger.info("[第三方服务对接->开启收流和获取发流信息] 等待收流超时 callId->{}, 发送回调", callId); + // 将信息写入redis中,以备后用 + redisTemplate.delete(receiveKey); OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder(); OkHttpClient client = httpClientBuilder.build(); String url = callBack + "?callId=" + callId; @@ -124,7 +129,7 @@ public class RtpController { otherRtpSendInfo.setReceivePort(localPort); otherRtpSendInfo.setCallId(callId); otherRtpSendInfo.setStream(stream); - String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_" + stream; + // 将信息写入redis中,以备后用 redisTemplate.opsForValue().set(receiveKey, otherRtpSendInfo); if (isSend != null && isSend) { @@ -148,9 +153,14 @@ public class RtpController { logger.info("[第三方服务对接->关闭收流] stream->{}", stream); MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer(); zlmServerFactory.closeRtpServer(mediaServerItem,stream); - String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_" + stream; - // 将信息写入redis中,以备后用 - redisTemplate.delete(receiveKey); + String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_*_" + stream; + List scan = RedisUtil.scan(redisTemplate, receiveKey); + if (scan.size() > 0) { + for (Object key : scan) { + // 将信息写入redis中,以备后用 + redisTemplate.delete(key); + } + } } @GetMapping(value = "/send/start") @@ -224,7 +234,7 @@ public class RtpController { hookSubscribe.addSubscribe(hookSubscribeForStreamChange, (mediaServerItemInUse, response)->{ dynamicTask.stop(uuid); - logger.info("[第三方服务对接->发送流] 流上线,开始发流 callId->{}", callId); + logger.info("[第三方服务对接->发送流] 流上线,开始发流 callId->{},param->{}", callId, JSONObject.toJSONString(param)); JSONObject jsonObject = zlmServerFactory.startSendRtpStream(mediaServerItem, param); System.out.println("========发流结果=========="); System.out.println(jsonObject); From c27e345edc6a92f485c1ef722ccaaa8ec6cbf5bf Mon Sep 17 00:00:00 2001 From: che_shuai Date: Thu, 13 Jul 2023 10:22:42 +0800 Subject: [PATCH 13/24] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=A4=9A=E7=BA=A7?= =?UTF-8?q?=E7=BA=A7=E8=81=94=E5=B9=B3=E5=8F=B0=E5=B9=B3=E5=8F=B0=E6=97=B6?= =?UTF-8?q?=EF=BC=8C=E4=B8=8A=E7=BA=A7=E5=B9=B3=E5=8F=B0=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E8=AE=BE=E5=A4=87=E5=BD=95=E5=83=8F=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E9=97=AE=E9=A2=98=E3=80=82=E9=97=AE=E9=A2=98=E8=AF=A6?= =?UTF-8?q?=E8=A7=81=20=20https://github.com/648540858/wvp-GB28181-pro/iss?= =?UTF-8?q?ues/914?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 1d4b23ef3..06a08e243 100644 --- 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 @@ -731,7 +731,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { .append("\r\n") .append("RecordInfo\r\n") .append("" +recordInfo.getSn() + "\r\n") - .append("" + recordInfo.getDeviceId() + "\r\n") + .append("" + recordInfo.getChannelId() + "\r\n") .append("" + recordInfo.getSumNum() + "\r\n"); if (recordInfo.getRecordList() == null ) { recordXml.append("\r\n"); From 9fc3db1f5e381378fd54818e0ba017df6be96fa9 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Thu, 13 Jul 2023 14:30:41 +0800 Subject: [PATCH 14/24] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8F=91=E6=B5=81?= =?UTF-8?q?=E9=9F=B3=E8=A7=86=E9=A2=91=E5=88=86=E5=BC=80=E5=8F=91=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/vmp/media/zlm/dto/HookType.java | 3 +- .../vmp/vmanager/bean/OtherRtpSendInfo.java | 89 +++++--- .../iot/vmp/vmanager/rtp/RtpController.java | 198 +++++++++++++----- 3 files changed, 211 insertions(+), 79 deletions(-) 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 index a4557e9a3..235cea7b7 100644 --- 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 @@ -21,5 +21,6 @@ public enum HookType { on_server_started, on_rtp_server_timeout, - on_server_keepalive + on_server_keepalive, + on_send_rtp_stopped } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/bean/OtherRtpSendInfo.java b/src/main/java/com/genersoft/iot/vmp/vmanager/bean/OtherRtpSendInfo.java index 9fea5c543..75c05d3b8 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/bean/OtherRtpSendInfo.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/bean/OtherRtpSendInfo.java @@ -5,12 +5,17 @@ public class OtherRtpSendInfo { /** * 发流IP */ - private String ip; + private String sendLocalIp; /** - * 发流端口 + * 音频发流端口 */ - private int port; + private int sendLocalPortForAudio; + + /** + * 视频发流端口 + */ + private int sendLocalPortForVideo; /** * 收流IP @@ -18,9 +23,14 @@ public class OtherRtpSendInfo { private String receiveIp; /** - * 收流端口 + * 音频收流端口 */ - private int receivePort; + private int receivePortForAudio; + + /** + * 视频收流端口 + */ + private int receivePortForVideo; /** * 会话ID @@ -48,23 +58,6 @@ public class OtherRtpSendInfo { private String pushSSRC; - - public String getIp() { - return ip; - } - - public void setIp(String ip) { - this.ip = ip; - } - - public int getPort() { - return port; - } - - public void setPort(int port) { - this.port = port; - } - public String getReceiveIp() { return receiveIp; } @@ -73,12 +66,20 @@ public class OtherRtpSendInfo { this.receiveIp = receiveIp; } - public int getReceivePort() { - return receivePort; + public int getReceivePortForAudio() { + return receivePortForAudio; } - public void setReceivePort(int receivePort) { - this.receivePort = receivePort; + public void setReceivePortForAudio(int receivePortForAudio) { + this.receivePortForAudio = receivePortForAudio; + } + + public int getReceivePortForVideo() { + return receivePortForVideo; + } + + public void setReceivePortForVideo(int receivePortForVideo) { + this.receivePortForVideo = receivePortForVideo; } public String getCallId() { @@ -121,15 +122,45 @@ public class OtherRtpSendInfo { this.pushSSRC = pushSSRC; } + + public String getSendLocalIp() { + return sendLocalIp; + } + + public void setSendLocalIp(String sendLocalIp) { + this.sendLocalIp = sendLocalIp; + } + + public int getSendLocalPortForAudio() { + return sendLocalPortForAudio; + } + + public void setSendLocalPortForAudio(int sendLocalPortForAudio) { + this.sendLocalPortForAudio = sendLocalPortForAudio; + } + + public int getSendLocalPortForVideo() { + return sendLocalPortForVideo; + } + + public void setSendLocalPortForVideo(int sendLocalPortForVideo) { + this.sendLocalPortForVideo = sendLocalPortForVideo; + } + @Override public String toString() { return "OtherRtpSendInfo{" + - " ip='" + ip + '\'' + - ", port=" + port + + "sendLocalIp='" + sendLocalIp + '\'' + + ", sendLocalPortForAudio=" + sendLocalPortForAudio + + ", sendLocalPortForVideo=" + sendLocalPortForVideo + ", receiveIp='" + receiveIp + '\'' + - ", receivePort=" + receivePort + + ", receivePortForAudio=" + receivePortForAudio + + ", receivePortForVideo=" + receivePortForVideo + ", callId='" + callId + '\'' + ", stream='" + stream + '\'' + + ", pushApp='" + pushApp + '\'' + + ", pushStream='" + pushStream + '\'' + + ", pushSSRC='" + pushSSRC + '\'' + '}'; } } 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 b7a7e1524..a9a66f5c4 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 @@ -98,10 +98,13 @@ public class RtpController { }catch (NumberFormatException e) { throw new ControllerException(ErrorCode.ERROR100.getCode(),"ssrc格式错误"); } - } String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_" + callId + "_" + stream; - int localPort = zlmServerFactory.createRTPServer(mediaServerItem, stream, ssrcInt, null, false, tcpMode); + int localPortForVideo = zlmServerFactory.createRTPServer(mediaServerItem, stream, ssrcInt, null, false, tcpMode); + int localPortForAudio = zlmServerFactory.createRTPServer(mediaServerItem, stream + "_a" , ssrcInt, null, false, tcpMode); + if (localPortForVideo == 0 || localPortForAudio == 0) { + throw new ControllerException(ErrorCode.ERROR100.getCode(), "获取端口失败"); + } // 注册回调如果rtp收流超时则通过回调发送通知 if (callBack != null) { HookSubscribeForRtpServerTimeout hookSubscribeForRtpServerTimeout = HookSubscribeFactory.on_rtp_server_timeout(stream, String.valueOf(ssrcInt), mediaServerItem.getId()); @@ -121,12 +124,14 @@ public class RtpController { } catch (IOException e) { logger.error("[第三方服务对接->开启收流和获取发流信息] 等待收流超时 callId->{}, 发送回调失败", callId, e); } + hookSubscribe.removeSubscribe(hookSubscribeForRtpServerTimeout); } }); } OtherRtpSendInfo otherRtpSendInfo = new OtherRtpSendInfo(); otherRtpSendInfo.setReceiveIp(mediaServerItem.getSdpIp()); - otherRtpSendInfo.setReceivePort(localPort); + otherRtpSendInfo.setReceivePortForVideo(localPortForVideo); + otherRtpSendInfo.setReceivePortForAudio(localPortForAudio); otherRtpSendInfo.setCallId(callId); otherRtpSendInfo.setStream(stream); @@ -135,11 +140,13 @@ public class RtpController { if (isSend != null && isSend) { String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + "_" + callId; // 预创建发流信息 - int port = sendRtpPortManager.getNextPort(mediaServerItem.getId()); + int portForVideo = sendRtpPortManager.getNextPort(mediaServerItem.getId()); + int portForAudio = sendRtpPortManager.getNextPort(mediaServerItem.getId()); // 将信息写入redis中,以备后用 redisTemplate.opsForValue().set(key, otherRtpSendInfo, 300, TimeUnit.SECONDS); - otherRtpSendInfo.setIp(mediaServerItem.getSdpIp()); - otherRtpSendInfo.setPort(port); + otherRtpSendInfo.setSendLocalIp(mediaServerItem.getSdpIp()); + otherRtpSendInfo.setSendLocalPortForVideo(portForVideo); + otherRtpSendInfo.setSendLocalPortForAudio(portForAudio); logger.info("[第三方服务对接->开启收流和获取发流信息] 结果,callId->{}, {}", callId, otherRtpSendInfo); } return otherRtpSendInfo; @@ -153,6 +160,7 @@ public class RtpController { logger.info("[第三方服务对接->关闭收流] stream->{}", stream); MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer(); zlmServerFactory.closeRtpServer(mediaServerItem,stream); + zlmServerFactory.closeRtpServer(mediaServerItem,stream + "_a"); String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_*_" + stream; List scan = RedisUtil.scan(redisTemplate, receiveKey); if (scan.size() > 0) { @@ -167,20 +175,51 @@ public class RtpController { @ResponseBody @Operation(summary = "发送流") @Parameter(name = "ssrc", description = "发送流的SSRC", required = true) - @Parameter(name = "ip", description = "目标IP", required = true) - @Parameter(name = "port", description = "目标端口", required = true) + @Parameter(name = "dstIpForAudio", description = "目标音频收流IP", required = false) + @Parameter(name = "dstIpForVideo", description = "目标视频收流IP", required = false) + @Parameter(name = "dstPortForAudio", description = "目标音频收流端口", required = false) + @Parameter(name = "dstPortForVideo", description = "目标视频收流端口", required = false) @Parameter(name = "app", description = "待发送应用名", required = true) @Parameter(name = "stream", description = "待发送流Id", required = true) @Parameter(name = "callId", description = "整个过程的唯一标识,不传则使用随机端口发流", required = true) - @Parameter(name = "onlyAudio", description = "是否只有音频", required = true) @Parameter(name = "isUdp", description = "是否为UDP", required = true) - @Parameter(name = "streamType", description = "流类型,1为es流,2为ps流, 默认es流", required = false) - @Parameter(name = "pt", description = "rtp的pt", required = true) - public void sendRTP(String ssrc, String ip, Integer port, String app, String stream, String callId, Boolean onlyAudio, Boolean isUdp, @RequestParam(required = false)Integer streamType, Integer pt) { - logger.info("[第三方服务对接->发送流] ssrc->{}, ip->{}, port->{}, app->{}, stream->{}, callId->{}, onlyAudio->{}, streamType->{}, pt->{}", - ssrc, ip, port, app, stream, callId, onlyAudio, streamType == 1? "ES":"PS", pt); - if (ObjectUtils.isEmpty(streamType)) { - streamType = 1; + @Parameter(name = "ptForAudio", description = "rtp的音频pt", required = false) + @Parameter(name = "ptForVideo", description = "rtp的视频pt", required = false) + public void sendRTP(String ssrc, + @RequestParam(required = false)String dstIpForAudio, + @RequestParam(required = false)String dstIpForVideo, + @RequestParam(required = false)Integer dstPortForAudio, + @RequestParam(required = false)Integer dstPortForVideo, + String app, + String stream, + String callId, + Boolean isUdp, + @RequestParam(required = false)Integer ptForAudio, + @RequestParam(required = false)Integer ptForVideo + ) { + logger.info("[第三方服务对接->发送流] " + + "ssrc->{}, \r\n" + + "dstIpForAudio->{}, \n" + + "dstIpForAudio->{}, \n" + + "dstPortForAudio->{}, \n" + + "dstPortForVideo->{}, \n" + + "app->{}, \n" + + "stream->{}, \n" + + "callId->{}, \n" + + "ptForAudio->{}, \n" + + "ptForVideo->{}", + ssrc, + dstIpForAudio, + dstIpForVideo, + dstPortForAudio, + dstPortForVideo, + app, + stream, + callId, + ptForAudio, + ptForVideo); + if (!((dstPortForAudio > 0 && !ObjectUtils.isEmpty(dstPortForAudio) || (dstPortForVideo > 0 && !ObjectUtils.isEmpty(dstIpForVideo))))) { + throw new ControllerException(ErrorCode.ERROR400.getCode(), "至少应该存在一组音频或视频发送参数"); } MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer(); String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + "_" + callId; @@ -192,32 +231,74 @@ public class RtpController { sendInfo.setPushStream(stream); sendInfo.setPushSSRC(ssrc); - Map param = new HashMap<>(12); - param.put("vhost","__defaultVhost__"); - param.put("app",app); - param.put("stream",stream); - param.put("ssrc", ssrc); + Map paramForAudio; + Map paramForVideo; + if (!ObjectUtils.isEmpty(dstIpForAudio) && dstPortForAudio > 0) { + paramForAudio = new HashMap<>(); + paramForAudio.put("vhost","__defaultVhost__"); + paramForAudio.put("app",app); + paramForAudio.put("stream",stream); + paramForAudio.put("ssrc", ssrc); - param.put("dst_url",ip); - param.put("dst_port", port); - String is_Udp = isUdp ? "1" : "0"; - param.put("is_udp", is_Udp); - param.put("src_port", sendInfo.getPort()); - param.put("use_ps", streamType==2 ? "1" : "0"); - param.put("only_audio", onlyAudio ? "1" : "0"); - param.put("pt", pt); + paramForAudio.put("dst_url", dstIpForAudio); + paramForAudio.put("dst_port", dstPortForAudio); + String is_Udp = isUdp ? "1" : "0"; + paramForAudio.put("is_udp", is_Udp); + paramForAudio.put("src_port", sendInfo.getSendLocalPortForAudio()); + paramForAudio.put("use_ps", "0"); + paramForAudio.put("only_audio", "1"); + if (ptForAudio != null) { + paramForAudio.put("pt", ptForAudio); + } + + } else { + paramForAudio = null; + } + if (!ObjectUtils.isEmpty(dstIpForVideo) && dstPortForVideo > 0) { + paramForVideo = new HashMap<>(); + paramForVideo.put("vhost","__defaultVhost__"); + paramForVideo.put("app",app); + paramForVideo.put("stream",stream); + paramForVideo.put("ssrc", ssrc); + + paramForVideo.put("dst_url", dstIpForVideo); + paramForVideo.put("dst_port", dstPortForVideo); + String is_Udp = isUdp ? "1" : "0"; + paramForVideo.put("is_udp", is_Udp); + paramForVideo.put("src_port", sendInfo.getSendLocalPortForVideo()); + paramForVideo.put("use_ps", "0"); + paramForVideo.put("only_audio", "0"); + if (ptForVideo != null) { + paramForVideo.put("pt", ptForVideo); + } + + } else { + paramForVideo = null; + } Boolean streamReady = zlmServerFactory.isStreamReady(mediaServerItem, app, stream); if (streamReady) { - logger.info("[第三方服务对接->发送流] 流存在,开始发流,callId->{}", callId); - JSONObject jsonObject = zlmServerFactory.startSendRtpStream(mediaServerItem, param); - if (jsonObject.getInteger("code") == 0) { - logger.info("[第三方服务对接->发送流] 发流成功,callId->{}", callId); - redisTemplate.opsForValue().set(key, sendInfo); - }else { - redisTemplate.delete(key); - logger.info("[第三方服务对接->发送流] 发流失败,callId->{}, {}", callId, jsonObject.getString("msg")); - throw new ControllerException(ErrorCode.ERROR100.getCode(), "[发流失败] " + jsonObject.getString("msg")); + if (paramForVideo != null) { + JSONObject jsonObject = zlmServerFactory.startSendRtpStream(mediaServerItem, paramForVideo); + if (jsonObject.getInteger("code") == 0) { + logger.info("[第三方服务对接->发送流] 视频流发流成功,callId->{},param->{}", callId, paramForVideo); + redisTemplate.opsForValue().set(key, sendInfo); + }else { + redisTemplate.delete(key); + logger.info("[第三方服务对接->发送流] 视频流发流失败,callId->{}, {}", callId, jsonObject.getString("msg")); + throw new ControllerException(ErrorCode.ERROR100.getCode(), "[视频流发流失败] " + jsonObject.getString("msg")); + } + } + if(paramForAudio != null) { + JSONObject jsonObject = zlmServerFactory.startSendRtpStream(mediaServerItem, paramForAudio); + if (jsonObject.getInteger("code") == 0) { + logger.info("[第三方服务对接->发送流] 音频流发流成功,callId->{},param->{}", callId, paramForAudio); + redisTemplate.opsForValue().set(key, sendInfo); + }else { + redisTemplate.delete(key); + logger.info("[第三方服务对接->发送流] 音频流发流失败,callId->{}, {}", callId, jsonObject.getString("msg")); + throw new ControllerException(ErrorCode.ERROR100.getCode(), "[音频流发流失败] " + jsonObject.getString("msg")); + } } }else { logger.info("[第三方服务对接->发送流] 流不存在,等待流上线,callId->{}", callId); @@ -231,21 +312,39 @@ public class RtpController { // 订阅 zlm启动事件, 新的zlm也会从这里进入系统 OtherRtpSendInfo finalSendInfo = sendInfo; + hookSubscribe.removeSubscribe(hookSubscribeForStreamChange); hookSubscribe.addSubscribe(hookSubscribeForStreamChange, (mediaServerItemInUse, response)->{ dynamicTask.stop(uuid); - logger.info("[第三方服务对接->发送流] 流上线,开始发流 callId->{},param->{}", callId, JSONObject.toJSONString(param)); - JSONObject jsonObject = zlmServerFactory.startSendRtpStream(mediaServerItem, param); - System.out.println("========发流结果=========="); - System.out.println(jsonObject); - if (jsonObject.getInteger("code") == 0) { - logger.info("[第三方服务对接->发送流] 发流成功,callId->{}", callId); - redisTemplate.opsForValue().set(key, finalSendInfo); - }else { - redisTemplate.delete(key); - logger.info("[第三方服务对接->发送流] 发流失败,callId->{}, {}", callId, jsonObject.getString("msg")); - throw new ControllerException(ErrorCode.ERROR100.getCode(), "[发流失败] " + jsonObject.getString("msg")); + logger.info("[第三方服务对接->发送流] 流上线,开始发流 callId->{}", callId); + try { + Thread.sleep(400); + } catch (InterruptedException e) { + throw new RuntimeException(e); } + if (paramForVideo != null) { + JSONObject jsonObject = zlmServerFactory.startSendRtpStream(mediaServerItem, paramForVideo); + if (jsonObject.getInteger("code") == 0) { + logger.info("[第三方服务对接->发送流] 视频流发流成功,callId->{},param->{}", callId, paramForVideo); + redisTemplate.opsForValue().set(key, finalSendInfo); + }else { + redisTemplate.delete(key); + logger.info("[第三方服务对接->发送流] 视频流发流失败,callId->{}, {}", callId, jsonObject.getString("msg")); + throw new ControllerException(ErrorCode.ERROR100.getCode(), "[视频流发流失败] " + jsonObject.getString("msg")); + } + } + if(paramForAudio != null) { + JSONObject jsonObject = zlmServerFactory.startSendRtpStream(mediaServerItem, paramForAudio); + if (jsonObject.getInteger("code") == 0) { + logger.info("[第三方服务对接->发送流] 音频流发流成功,callId->{},param->{}", callId, paramForAudio); + redisTemplate.opsForValue().set(key, finalSendInfo); + }else { + redisTemplate.delete(key); + logger.info("[第三方服务对接->发送流] 音频流发流失败,callId->{}, {}", callId, jsonObject.getString("msg")); + throw new ControllerException(ErrorCode.ERROR100.getCode(), "[音频流发流失败] " + jsonObject.getString("msg")); + } + } + hookSubscribe.removeSubscribe(hookSubscribeForStreamChange); }); } } @@ -274,6 +373,7 @@ public class RtpController { }else { logger.info("[第三方服务对接->关闭发送流] 成功 callId->{}", callId); } + redisTemplate.delete(key); } } From ef5018de2d86bd4728a75ddc0eccd11b812375dc Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Thu, 13 Jul 2023 14:57:30 +0800 Subject: [PATCH 15/24] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=90=88=E5=B9=B6?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/genersoft/iot/vmp/conf/MediaConfig.java | 8 -------- .../iot/vmp/gb28181/conf/ServerLoggerImpl.java | 3 ++- .../iot/vmp/vmanager/rtp/RtpController.java | 12 +----------- .../iot/vmp/web/gb28181/ApiDeviceController.java | 14 ++------------ src/main/resources/wvpssl.jks | Bin 2196 -> 0 bytes 5 files changed, 5 insertions(+), 32 deletions(-) delete mode 100644 src/main/resources/wvpssl.jks 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 93d265e43..20ed8cb1f 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java @@ -233,12 +233,4 @@ public class MediaConfig{ } return false; } - - public String getRtpSendPortRange() { - return rtpSendPortRange; - } - - public void setRtpSendPortRange(String rtpSendPortRange) { - this.rtpSendPortRange = rtpSendPortRange; - } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/conf/ServerLoggerImpl.java b/src/main/java/com/genersoft/iot/vmp/gb28181/conf/ServerLoggerImpl.java index 19e1906c3..c7b1f6e6a 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/conf/ServerLoggerImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/conf/ServerLoggerImpl.java @@ -1,5 +1,6 @@ package com.genersoft.iot.vmp.gb28181.conf; +import gov.nist.core.CommonLogger; import gov.nist.core.ServerLogger; import gov.nist.core.StackLogger; import gov.nist.javax.sip.message.SIPMessage; @@ -84,7 +85,7 @@ public class ServerLoggerImpl implements ServerLogger { } if(sipStack instanceof SIPTransactionStack) { this.sipStack = (SIPTransactionStack)sipStack; - this.stackLogger = this.sipStack.getStackLogger(); + this.stackLogger = CommonLogger.getLogger(SIPTransactionStack.class); } } } 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 c4c1df99c..94f1ba753 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 @@ -7,16 +7,12 @@ import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.exception.ControllerException; import com.genersoft.iot.vmp.media.zlm.SendRtpPortManager; import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; -import com.genersoft.iot.vmp.media.zlm.SendRtpPortManager; -import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; 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.IDeviceChannelService; -import com.genersoft.iot.vmp.service.IDeviceService; import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.utils.redis.RedisUtil; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; @@ -39,7 +35,6 @@ import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeUnit; @SuppressWarnings("rawtypes") @Tag(name = "第三方服务对接") @@ -62,16 +57,12 @@ public class RtpController { @Autowired private IMediaServerService mediaServerService; - @Autowired - private SendRtpPortManager sendRtpPortManager; - @Autowired private UserSetting userSetting; @Autowired private DynamicTask dynamicTask; - @Autowired private RedisTemplate redisTemplate; @@ -136,7 +127,7 @@ public class RtpController { } }); } - String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + callId; + String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + "_" + callId; OtherRtpSendInfo otherRtpSendInfo = new OtherRtpSendInfo(); otherRtpSendInfo.setReceiveIp(mediaServerItem.getSdpIp()); otherRtpSendInfo.setReceivePortForVideo(localPortForVideo); @@ -147,7 +138,6 @@ public class RtpController { // 将信息写入redis中,以备后用 redisTemplate.opsForValue().set(receiveKey, otherRtpSendInfo); if (isSend != null && isSend) { - String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + "_" + callId; // 预创建发流信息 int portForVideo = sendRtpPortManager.getNextPort(mediaServerItem.getId()); int portForAudio = sendRtpPortManager.getNextPort(mediaServerItem.getId()); diff --git a/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiDeviceController.java b/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiDeviceController.java index d8c209306..7b59f7f71 100644 --- a/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiDeviceController.java +++ b/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiDeviceController.java @@ -18,7 +18,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.ObjectUtils; -import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -115,20 +114,11 @@ public class ApiDeviceController { @RequestParam(required = false)String q, @RequestParam(required = false)Boolean online ){ -// if (logger.isDebugEnabled()) { -// logger.debug("查询所有视频设备API调用"); -// } + JSONObject result = new JSONObject(); - // 查询设备是否存在 -// Device device = storager.queryVideoDevice(serial); -// if (device == null) { -// result.put("ChannelCount", 0); -// result.put("ChannelList", "[]"); -// return result; -// } List deviceChannels; List channelIds = null; - if (!StringUtils.isEmpty(code)) { + if (!ObjectUtils.isEmpty(code)) { String[] split = code.trim().split(","); channelIds = Arrays.asList(split); } diff --git a/src/main/resources/wvpssl.jks b/src/main/resources/wvpssl.jks deleted file mode 100644 index 92b98b77a52553ec4fc23caf8bb08d5af33b18f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2196 zcmcK4`8(8$9tZIG&Wte(L&m<(Oo+^w(BLR#$xvwK7@4sm1x%YWaf583W^TX?>&+}QH_x|esDhLDu9~SVvV4)$D zz(DdLBVF=&)IlH~Fo6c$Cm><`$6){zPy-(U03HyO23_Xbs*D)a>A11Bq5gZqBexNv zmOhFTsPLm-o%Xe#&@2NUj<}EPK9O#cPTSGFGCSv@qn!83YoM)k4W&y^~2HdC?2G+UI&Pi&)V{KA7UpWOzpYDIH@KfA!1=8Y!_BXxD! zWlnus{l;@EaRf~YiV59%$e|i}s5WF3Un9D6QfN`Q2C(*>UV5>gtDN#yH8Qy$ zU9invV@L2Y!^Q#9)l(ZqJMMUI>CyHFKMh@A)pTlm&A&=b$+2oh3)$n#PVSv3*N3NM z0vSb?@?%NExTESBcV{EnBUa*DP^`p+UyN8E{{>3IP zsP)fbu_fLNLRv*k6vKfw(sq88@}>TzP^#lRMH#Y-a4}p_e^=KqoJn5?sUm|c#$r+0 z%`w-%I2~~7XRCZU0_YV(8dTy>QT}_0Ro9Z#0>AWhI_lQ^0GGh=DqCjmpIcK=C6A{IAmv^P zXL%Q~ZN<#3QK z&hG|#Jb22TcF%TMOx=O2uHDDJP}nuPYv^03kjcDuemg)dN3Oo-GkuGkv0z%~A9$+I zP`nha-c;4QeRQf?op0>YA4_+=(u#Xpy1!!74rHLC! z#TThM6_p}FYziiAK;{wWU09rGuJvevtls#%f9ROD{cMf5a({t=`- z36gT#g!C@h?oky-$a+>UWFfI+?f93H%NWavgKG`$ZpX`95Xktc&A-<}8U6 z(j}oS>c=Z5wbafDqB_)ypHBq8aum|q6Pmn2MQkCkvbR1k`{0fbnk#7}nSIf=!mp<6 zb`SB&$DyV>?$F}y0w~(}j8?;lT}3!Xu3`q)i&A3yZbWfRJwUcC*$2mw82)U@Ele3w z67WqtX7Ax+5o9h>&b#vSLyNqNI}G^tQ^@FyL3K3rF@o6H6DUm1i{8BR)=qoS_!A3- zV@im0Gy?4nY3zl$PwMV&m%k*$*<=JwE~Ekh%h8xR;<)!DQ%7q566~20?s7PuH)9VB z0YE@0nxH_CJG{6Y5-JWAb?EeuBfWvg^-}7enTvF*PTqM>|K}19f8=n904OIR!|)Gf zYh{L5u0buSr!5530k#)mS(RYZCRsj+76>M%u5X8p)#eH^P+-a_KENGc} z%g{i^|D(9?BTK>I2K1CK%p&yadM(FUGFY&wtjipq<4vitwirj?ew|y}7bj)4>s;4u2;~fy6g-F?kDQtIvo`6KE}W@iXcX zYzGI6>i1V2OxQHJ^_783E=N_TswIEk4#0R=akOh1dQjMz=$@hp? MBy-i6op7^%1J2R82><{9 From c42d391290adc50348807d623c4b689ab1f109fc Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Fri, 14 Jul 2023 08:34:15 +0800 Subject: [PATCH 16/24] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=AD=98=E5=82=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/vmp/media/zlm/SendRtpPortManager.java | 56 +++++++++++++++---- .../iot/vmp/vmanager/rtp/RtpController.java | 5 +- 2 files changed, 48 insertions(+), 13 deletions(-) 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 8366a4a2d..1fb8256c6 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 @@ -1,13 +1,20 @@ 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.utils.redis.RedisUtil; 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.Component; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + @Component public class SendRtpPortManager { @@ -29,27 +36,54 @@ public class SendRtpPortManager { } public int getNextPort(String mediaServerId) { - String key = KEY + userSetting.getServerId() + "_" + mediaServerId; - MediaSendRtpPortInfo mediaSendRtpPortInfo = (MediaSendRtpPortInfo)redisTemplate.opsForValue().get(key); + String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + + userSetting.getServerId() + "_*"; + List queryResult = RedisUtil.scan(redisTemplate, key); + Map sendRtpItemMap = new HashMap<>(); + + for (Object o : queryResult) { + SendRtpItem sendRtpItem = (SendRtpItem) redisTemplate.opsForValue().get(o); + if (sendRtpItem != null) { + sendRtpItemMap.put(sendRtpItem.getLocalPort(), sendRtpItem); + } + } + + String sendIndexKey = KEY + userSetting.getServerId() + "_" + mediaServerId; + MediaSendRtpPortInfo mediaSendRtpPortInfo = (MediaSendRtpPortInfo)redisTemplate.opsForValue().get(sendIndexKey); if (mediaSendRtpPortInfo == null) { logger.warn("[发送端口管理] 获取{}的发送端口时未找到端口信息", mediaSendRtpPortInfo); return 0; } + int port = getPort(mediaSendRtpPortInfo.getCurrent(), + mediaSendRtpPortInfo.getStart(), + mediaSendRtpPortInfo.getEnd(), checkPort -> sendRtpItemMap.get(checkPort) == null); + + mediaSendRtpPortInfo.setCurrent(port); + redisTemplate.opsForValue().set(sendIndexKey, mediaSendRtpPortInfo); + return port; + } + + interface CheckPortCallback{ + boolean check(int port); + } + + private int getPort(int current, int start, int end, CheckPortCallback checkPortCallback) { int port; - if (mediaSendRtpPortInfo.getCurrent() %2 != 0) { - port = mediaSendRtpPortInfo.getCurrent() + 1; + if (current %2 != 0) { + port = current + 1; }else { - port = mediaSendRtpPortInfo.getCurrent() + 2; + port = current + 2; } - if (port > mediaSendRtpPortInfo.getEnd()) { - if (mediaSendRtpPortInfo.getStart() %2 != 0) { - port = mediaSendRtpPortInfo.getStart() + 1; + if (port > end) { + if (start %2 != 0) { + port = start + 1; }else { - port = mediaSendRtpPortInfo.getStart(); + port = start; } } - mediaSendRtpPortInfo.setCurrent(port); - redisTemplate.opsForValue().set(key, mediaSendRtpPortInfo); + if (!checkPortCallback.check(port)) { + return getPort(port, start, end, checkPortCallback); + } return port; } } 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 a9a66f5c4..18215223f 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 @@ -142,11 +142,12 @@ public class RtpController { // 预创建发流信息 int portForVideo = sendRtpPortManager.getNextPort(mediaServerItem.getId()); int portForAudio = sendRtpPortManager.getNextPort(mediaServerItem.getId()); - // 将信息写入redis中,以备后用 - redisTemplate.opsForValue().set(key, otherRtpSendInfo, 300, TimeUnit.SECONDS); + otherRtpSendInfo.setSendLocalIp(mediaServerItem.getSdpIp()); otherRtpSendInfo.setSendLocalPortForVideo(portForVideo); otherRtpSendInfo.setSendLocalPortForAudio(portForAudio); + // 将信息写入redis中,以备后用 + redisTemplate.opsForValue().set(key, otherRtpSendInfo, 300, TimeUnit.SECONDS); logger.info("[第三方服务对接->开启收流和获取发流信息] 结果,callId->{}, {}", callId, otherRtpSendInfo); } return otherRtpSendInfo; From 4162706ec43375058df381e9f23f648b01f1dfb3 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Fri, 14 Jul 2023 09:10:59 +0800 Subject: [PATCH 17/24] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=9B=A0=E4=B8=BA?= =?UTF-8?q?=E5=BF=83=E8=B7=B3=E9=87=8D=E5=8F=91=E5=AF=BC=E8=87=B4=E7=9A=84?= =?UTF-8?q?=E5=BF=83=E8=B7=B3=E9=97=B4=E9=9A=94=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../message/notify/cmd/KeepaliveNotifyMessageHandler.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java index 5ec76dd80..729eec392 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java @@ -78,7 +78,9 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp device.setKeepaliveIntervalTime(60); }else { long lastTime = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(device.getKeepaliveTime()); - device.setKeepaliveIntervalTime(new Long(System.currentTimeMillis()/1000-lastTime).intValue()); + if (System.currentTimeMillis()/1000-lastTime > 10) { + device.setKeepaliveIntervalTime(new Long(System.currentTimeMillis()/1000-lastTime).intValue()); + } } device.setKeepaliveTime(DateUtil.getNow()); From 287d42c1968a53c97ee2eff20bed444d842a41b5 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Fri, 14 Jul 2023 11:27:58 +0800 Subject: [PATCH 18/24] =?UTF-8?q?=E6=8E=A8=E6=B5=81=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E5=BC=80=E5=90=AF=E9=9F=B3=E9=A2=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) 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 d23c6c7e5..52b3664e7 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java @@ -222,7 +222,7 @@ public class ZLMHttpHookListener { HookResultForOnPublish result = HookResultForOnPublish.SUCCESS(); - + result.setEnable_audio(true); taskExecutor.execute(() -> { ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_publish, json); if (subscribe != null) { @@ -250,7 +250,6 @@ public class ZLMHttpHookListener { // 如果是录像下载就设置视频间隔十秒 if (ssrcTransactionForAll.get(0).getType() == VideoStreamSessionManager.SessionType.download) { result.setMp4_max_second(10); - result.setEnable_audio(true); result.setEnable_mp4(true); } } @@ -275,12 +274,8 @@ public class ZLMHttpHookListener { } if (param.getApp().equalsIgnoreCase("rtp")) { String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_" + param.getStream(); - System.out.println(receiveKey); OtherRtpSendInfo otherRtpSendInfo = (OtherRtpSendInfo)redisTemplate.opsForValue().get(receiveKey); - System.out.println("otherRtpSendInfo != null ====>" + (otherRtpSendInfo != null)); if (otherRtpSendInfo != null) { - System.out.println("otherRtpSendInfo != null"); - result.setEnable_audio(true); result.setEnable_mp4(true); } } From a9f88be8c592664332de2587f9304e371ab34192 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Fri, 14 Jul 2023 19:46:41 +0800 Subject: [PATCH 19/24] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=8B=89=E6=B5=81?= =?UTF-8?q?=E4=BB=A3=E7=90=86=E7=9A=84=E6=B7=BB=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/StreamProxyServiceImpl.java | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 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 71711389c..a1c5b1c42 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 @@ -4,14 +4,13 @@ import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.genersoft.iot.vmp.common.GeneralCallback; import com.genersoft.iot.vmp.common.StreamInfo; +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.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.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.zlm.dto.StreamProxyItem; import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; @@ -41,6 +40,7 @@ import org.springframework.util.ObjectUtils; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; /** * 视频代理业务 @@ -92,6 +92,9 @@ public class StreamProxyServiceImpl implements IStreamProxyService { @Autowired private ZlmHttpHookSubscribe hookSubscribe; + @Autowired + private DynamicTask dynamicTask; + @Autowired DataSourceTransactionManager dataSourceTransactionManager; @@ -158,17 +161,28 @@ public class StreamProxyServiceImpl implements IStreamProxyService { 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); - callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo); - }); + 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()) { JSONObject jsonObject = addStreamProxyToZlm(param); if (jsonObject != null && jsonObject.getInteger("code") == 0) { - hookSubscribe.removeSubscribe(hookSubscribeForStreamChange); + dynamicTask.stop(talkKey); StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream( mediaInfo, param.getApp(), param.getStream(), null, null); callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo); @@ -295,10 +309,10 @@ public class StreamProxyServiceImpl implements IStreamProxyService { return null; } if ("default".equals(param.getType())){ - result = zlmresTfulUtils.addStreamProxy(mediaServerItem, param.getApp(), param.getStream(), param.getUrl(), + result = zlmresTfulUtils.addStreamProxy(mediaServerItem, param.getApp(), param.getStream(), param.getUrl().trim(), param.isEnableAudio(), param.isEnableMp4(), param.getRtpType()); }else if ("ffmpeg".equals(param.getType())) { - result = zlmresTfulUtils.addFFmpegSource(mediaServerItem, param.getSrcUrl(), param.getDstUrl(), + result = zlmresTfulUtils.addFFmpegSource(mediaServerItem, param.getSrcUrl().trim(), param.getDstUrl(), param.getTimeoutMs() + "", param.isEnableAudio(), param.isEnableMp4(), param.getFfmpegCmdKey()); } From 4f2cd4113462764ae2d056dfed9010c1c764321f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E4=BF=8A=E6=9D=B0?= <502612493@qq.com> Date: Mon, 17 Jul 2023 10:54:34 +0800 Subject: [PATCH 20/24] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B8=8A=E7=BA=A7?= =?UTF-8?q?=E5=B9=B3=E5=8F=B0=E7=82=B9=E6=92=AD=E8=BF=87=E7=A8=8B=E4=B8=AD?= =?UTF-8?q?=E6=9C=AC=E5=B9=B3=E5=8F=B0=E7=94=9F=E6=88=90=E7=9A=84ssrc?= =?UTF-8?q?=E5=B9=B6=E6=B2=A1=E6=9C=89=E5=9C=A8openRtp=E4=B8=AD=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E5=AF=BC=E8=87=B4=E4=BC=9A=E6=96=B0=E7=94=9F=E6=88=90?= =?UTF-8?q?ssrc=E5=92=8C=E4=B9=8B=E5=89=8D=E7=9A=84=E5=86=B2=E7=AA=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../request/impl/InviteRequestProcessor.java | 22 ++++++++++--------- .../vmp/media/zlm/ZLMHttpHookListener.java | 2 +- .../iot/vmp/service/IPlayService.java | 2 +- .../iot/vmp/service/impl/PlayServiceImpl.java | 6 ++--- .../vmanager/gb28181/play/PlayController.java | 2 +- .../vmp/web/gb28181/ApiStreamController.java | 2 +- 6 files changed, 19 insertions(+), 17 deletions(-) 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 c0a1fec9c..a0f43e776 100644 --- 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 @@ -476,16 +476,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements } }); }else { - sendRtpItem.setPlayType(InviteStreamType.PLAY); - String streamId = null; - if (mediaServerItem.isRtpEnable()) { - streamId = String.format("%s_%s", device.getDeviceId(), channelId); - }else { - streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase(); - } - sendRtpItem.setStreamId(streamId); - redisCatchStorage.updateSendRTPSever(sendRtpItem); - playService.play(mediaServerItem, device.getDeviceId(), channelId, ((code, msg, data) -> { + + SSRCInfo ssrcInfo = playService.play(mediaServerItem, device.getDeviceId(), channelId, ssrc, ((code, msg, data) -> { if (code == InviteErrorCode.SUCCESS.getCode()){ hookEvent.run(code, msg, data); }else if (code == InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode() || code == InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode()){ @@ -496,6 +488,16 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements errorEvent.run(code, msg, data); } })); + sendRtpItem.setPlayType(InviteStreamType.PLAY); + String streamId = null; + if (mediaServerItem.isRtpEnable()) { + streamId = String.format("%s_%s", device.getDeviceId(), channelId); + }else { + streamId = String.format("%08x", Integer.parseInt(ssrcInfo.getSsrc())).toUpperCase(); + } + sendRtpItem.setStreamId(streamId); + sendRtpItem.setSsrc(ssrcInfo.getSsrc()); + redisCatchStorage.updateSendRTPSever(sendRtpItem); } } else if (gbStream != null) { 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 eac7401df..b7835659b 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java @@ -586,7 +586,7 @@ public class ZLMHttpHookListener { resultHolder.put(key, uuid, result); if (!exist) { - playService.play(mediaInfo, deviceId, channelId, (code, message, data) -> { + playService.play(mediaInfo, deviceId, channelId, null, (code, message, data) -> { msg.setData(new HookResult(code, message)); resultHolder.invokeResult(msg); }); 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 51624112d..bd2bc885e 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java @@ -18,7 +18,7 @@ public interface IPlayService { void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ErrorCallback callback); - SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, ErrorCallback callback); + SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback callback); MediaServerItem getNewMediaServerItem(Device device); 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 519013920..34d40c805 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 @@ -116,7 +116,7 @@ public class PlayServiceImpl implements IPlayService { @Override - public SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, ErrorCallback callback) { + public SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback callback) { if (mediaServerItem == null) { throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到可用的zlm"); } @@ -162,7 +162,7 @@ public class PlayServiceImpl implements IPlayService { if (mediaServerItem.isRtpEnable()) { streamId = String.format("%s_%s", device.getDeviceId(), channelId); } - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, device.isSsrcCheck(), false, 0, false, device.getStreamModeForParam()); + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, ssrc, device.isSsrcCheck(), false, 0, 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, @@ -1154,7 +1154,7 @@ public class PlayServiceImpl implements IPlayService { } MediaServerItem newMediaServerItem = getNewMediaServerItem(device); - play(newMediaServerItem, deviceId, channelId, (code, msg, data)->{ + play(newMediaServerItem, deviceId, channelId, null, (code, msg, data)->{ if (code == InviteErrorCode.SUCCESS.getCode()) { InviteInfo inviteInfoForPlay = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); if (inviteInfoForPlay != null && inviteInfoForPlay.getStreamInfo() != null) { 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 9e41f22da..86450f4d9 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java @@ -116,7 +116,7 @@ public class PlayController { // 录像查询以channelId作为deviceId查询 resultHolder.put(key, uuid, result); - playService.play(newMediaServerItem, deviceId, channelId, (code, msg, data) -> { + playService.play(newMediaServerItem, deviceId, channelId, null, (code, msg, data) -> { WVPResult wvpResult = new WVPResult<>(); if (code == InviteErrorCode.SUCCESS.getCode()) { wvpResult.setCode(ErrorCode.SUCCESS.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 556adf62c..18fdfa939 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 @@ -122,7 +122,7 @@ public class ApiStreamController { MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); - playService.play(newMediaServerItem, serial, code, (errorCode, msg, data) -> { + 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) { From 153523a32fffdde55f0eea9075679121da689f96 Mon Sep 17 00:00:00 2001 From: xiaoQQya Date: Mon, 17 Jul 2023 15:51:09 +0800 Subject: [PATCH 21/24] =?UTF-8?q?perf(config):=20=E8=A1=A5=E5=85=A8=20all-?= =?UTF-8?q?application.yml=20=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6?= 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 ef247f7fc..e982b2b9c 100644 --- a/src/main/resources/all-application.yml +++ b/src/main/resources/all-application.yml @@ -145,6 +145,8 @@ media: enable: true # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功 port-range: 30000,30500 # 端口范围 + # [可选] 国标级联在此范围内选择端口发送媒体流 + send-port-range: 30000,30500 # 端口范围 # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用 record-assist-port: 0 From 7a120c6da4911692f143d7111fd5edaa7036a9f7 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Mon, 17 Jul 2023 16:54:00 +0800 Subject: [PATCH 22/24] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java | 2 ++ .../com/genersoft/iot/vmp/media/zlm/SendRtpPortManager.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) 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 18ccaf410..7e355e54f 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 @@ -44,6 +44,8 @@ public class DefaultProperties { // 定义应用程序打算多久审计一次 SIP 堆栈,了解其内部线程的健康状况(该属性指定连续审计之间的时间(以毫秒为单位)) properties.setProperty("gov.nist.javax.sip.THREAD_AUDIT_INTERVAL_IN_MILLISECS", "30000"); +// properties.setProperty("gov.nist.javax.sip.MESSAGE_PROCESSOR_FACTORY", "gov.nist.javax.sip.stack.NioMessageProcessorFactory"); + /** * sip_server_log.log 和 sip_debug_log.log ERROR, INFO, WARNING, OFF, DEBUG, TRACE */ 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 8366a4a2d..1b9d25e79 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 @@ -32,7 +32,7 @@ public class SendRtpPortManager { String key = KEY + userSetting.getServerId() + "_" + mediaServerId; MediaSendRtpPortInfo mediaSendRtpPortInfo = (MediaSendRtpPortInfo)redisTemplate.opsForValue().get(key); if (mediaSendRtpPortInfo == null) { - logger.warn("[发送端口管理] 获取{}的发送端口时未找到端口信息", mediaSendRtpPortInfo); + logger.warn("[发送端口管理] 获取{}的发送端口时未找到端口信息", mediaServerId); return 0; } int port; From 5c49627012996aedb802b81e64c4776f9874f0a7 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Mon, 17 Jul 2023 16:55:41 +0800 Subject: [PATCH 23/24] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=8F=91=E6=B5=81?= =?UTF-8?q?=E7=AB=AF=E5=8F=A3=E5=88=86=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/vmp/media/zlm/SendRtpPortManager.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) 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 1fb8256c6..5c857da86 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 @@ -36,6 +36,13 @@ public class SendRtpPortManager { } public int getNextPort(String mediaServerId) { + String sendIndexKey = KEY + userSetting.getServerId() + "_" + mediaServerId; + MediaSendRtpPortInfo mediaSendRtpPortInfo = (MediaSendRtpPortInfo)redisTemplate.opsForValue().get(sendIndexKey); + if (mediaSendRtpPortInfo == null) { + logger.warn("[发送端口管理] 获取{}的发送端口时未找到端口信息", mediaSendRtpPortInfo); + return 0; + } + String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + userSetting.getServerId() + "_*"; List queryResult = RedisUtil.scan(redisTemplate, key); @@ -48,12 +55,6 @@ public class SendRtpPortManager { } } - String sendIndexKey = KEY + userSetting.getServerId() + "_" + mediaServerId; - MediaSendRtpPortInfo mediaSendRtpPortInfo = (MediaSendRtpPortInfo)redisTemplate.opsForValue().get(sendIndexKey); - if (mediaSendRtpPortInfo == null) { - logger.warn("[发送端口管理] 获取{}的发送端口时未找到端口信息", mediaSendRtpPortInfo); - return 0; - } int port = getPort(mediaSendRtpPortInfo.getCurrent(), mediaSendRtpPortInfo.getStart(), mediaSendRtpPortInfo.getEnd(), checkPort -> sendRtpItemMap.get(checkPort) == null); From 19533c8f4d6f63793cbfe042196bf9058ca4a2ee Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Mon, 17 Jul 2023 17:28:49 +0800 Subject: [PATCH 24/24] =?UTF-8?q?=E5=90=88=E5=B9=B6=E5=88=86=E6=94=AF?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java | 6 ++++++ 1 file changed, 6 insertions(+) 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 f72924846..d19d98b56 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java @@ -5,6 +5,7 @@ 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.*; @@ -26,11 +27,13 @@ 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.vmanager.bean.ErrorCode; +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.data.redis.core.RedisTemplate; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.util.ObjectUtils; import org.springframework.web.bind.annotation.*; @@ -117,6 +120,9 @@ public class ZLMHttpHookListener { @Autowired private ThreadPoolTaskExecutor taskExecutor; + @Autowired + private RedisTemplate redisTemplate; + /** * 服务器定时上报时间,上报间隔可配置,默认10s上报一次 */