Commit 2466a248609b2a9b8eeee08c1378b2a440db475d
1 parent
c62a8986
去除发送流端口范围
Showing
13 changed files
with
129 additions
and
148 deletions
pom.xml
| @@ -11,7 +11,7 @@ | @@ -11,7 +11,7 @@ | ||
| 11 | 11 | ||
| 12 | <groupId>com.genersoft</groupId> | 12 | <groupId>com.genersoft</groupId> |
| 13 | <artifactId>wvp-pro</artifactId> | 13 | <artifactId>wvp-pro</artifactId> |
| 14 | - <version>2.3.2</version> | 14 | + <version>2.6.6</version> |
| 15 | <name>web video platform</name> | 15 | <name>web video platform</name> |
| 16 | <description>国标28181视频平台</description> | 16 | <description>国标28181视频平台</description> |
| 17 | 17 |
src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java
| 1 | package com.genersoft.iot.vmp.conf; | 1 | package com.genersoft.iot.vmp.conf; |
| 2 | 2 | ||
| 3 | -import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; | ||
| 4 | import org.slf4j.Logger; | 3 | import org.slf4j.Logger; |
| 5 | import org.slf4j.LoggerFactory; | 4 | import org.slf4j.LoggerFactory; |
| 6 | -import org.springframework.beans.factory.annotation.Autowired; | ||
| 7 | -import org.springframework.context.annotation.Bean; | ||
| 8 | import org.springframework.scheduling.annotation.Scheduled; | 5 | import org.springframework.scheduling.annotation.Scheduled; |
| 9 | import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; | 6 | import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; |
| 10 | import org.springframework.stereotype.Component; | 7 | import org.springframework.stereotype.Component; |
| @@ -101,12 +98,14 @@ public class DynamicTask { | @@ -101,12 +98,14 @@ public class DynamicTask { | ||
| 101 | } | 98 | } |
| 102 | } | 99 | } |
| 103 | 100 | ||
| 104 | - public void stop(String key) { | ||
| 105 | - if (futureMap.get(key) != null && !futureMap.get(key).isCancelled()) { | ||
| 106 | - futureMap.get(key).cancel(false); | 101 | + public boolean stop(String key) { |
| 102 | + boolean result = false; | ||
| 103 | + if (futureMap.get(key) != null && !futureMap.get(key).isCancelled() && !futureMap.get(key).isDone()) { | ||
| 104 | + result = futureMap.get(key).cancel(false); | ||
| 107 | futureMap.remove(key); | 105 | futureMap.remove(key); |
| 108 | runnableMap.remove(key); | 106 | runnableMap.remove(key); |
| 109 | } | 107 | } |
| 108 | + return result; | ||
| 110 | } | 109 | } |
| 111 | 110 | ||
| 112 | public boolean contains(String key) { | 111 | public boolean contains(String key) { |
src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java
| @@ -2,13 +2,11 @@ package com.genersoft.iot.vmp.conf; | @@ -2,13 +2,11 @@ package com.genersoft.iot.vmp.conf; | ||
| 2 | 2 | ||
| 3 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | 3 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 4 | import com.genersoft.iot.vmp.utils.DateUtil; | 4 | import com.genersoft.iot.vmp.utils.DateUtil; |
| 5 | -import com.genersoft.iot.vmp.vmanager.gb28181.device.DeviceQuery; | ||
| 6 | import org.slf4j.Logger; | 5 | import org.slf4j.Logger; |
| 7 | import org.slf4j.LoggerFactory; | 6 | import org.slf4j.LoggerFactory; |
| 8 | import org.springframework.beans.factory.annotation.Value; | 7 | import org.springframework.beans.factory.annotation.Value; |
| 9 | import org.springframework.context.annotation.Configuration; | 8 | import org.springframework.context.annotation.Configuration; |
| 10 | import org.springframework.util.ObjectUtils; | 9 | import org.springframework.util.ObjectUtils; |
| 11 | -import org.springframework.util.StringUtils; | ||
| 12 | 10 | ||
| 13 | import java.net.InetAddress; | 11 | import java.net.InetAddress; |
| 14 | import java.net.UnknownHostException; | 12 | import java.net.UnknownHostException; |
| @@ -75,10 +73,6 @@ public class MediaConfig{ | @@ -75,10 +73,6 @@ public class MediaConfig{ | ||
| 75 | @Value("${media.rtp.port-range}") | 73 | @Value("${media.rtp.port-range}") |
| 76 | private String rtpPortRange; | 74 | private String rtpPortRange; |
| 77 | 75 | ||
| 78 | - | ||
| 79 | - @Value("${media.rtp.send-port-range}") | ||
| 80 | - private String sendRtpPortRange; | ||
| 81 | - | ||
| 82 | @Value("${media.record-assist-port:0}") | 76 | @Value("${media.record-assist-port:0}") |
| 83 | private Integer recordAssistPort = 0; | 77 | private Integer recordAssistPort = 0; |
| 84 | 78 | ||
| @@ -191,10 +185,6 @@ public class MediaConfig{ | @@ -191,10 +185,6 @@ public class MediaConfig{ | ||
| 191 | return sipDomain; | 185 | return sipDomain; |
| 192 | } | 186 | } |
| 193 | 187 | ||
| 194 | - public String getSendRtpPortRange() { | ||
| 195 | - return sendRtpPortRange; | ||
| 196 | - } | ||
| 197 | - | ||
| 198 | public MediaServerItem getMediaSerItem(){ | 188 | public MediaServerItem getMediaSerItem(){ |
| 199 | MediaServerItem mediaServerItem = new MediaServerItem(); | 189 | MediaServerItem mediaServerItem = new MediaServerItem(); |
| 200 | mediaServerItem.setId(id); | 190 | mediaServerItem.setId(id); |
| @@ -214,9 +204,8 @@ public class MediaConfig{ | @@ -214,9 +204,8 @@ public class MediaConfig{ | ||
| 214 | mediaServerItem.setSecret(secret); | 204 | mediaServerItem.setSecret(secret); |
| 215 | mediaServerItem.setRtpEnable(rtpEnable); | 205 | mediaServerItem.setRtpEnable(rtpEnable); |
| 216 | mediaServerItem.setRtpPortRange(rtpPortRange); | 206 | mediaServerItem.setRtpPortRange(rtpPortRange); |
| 217 | - mediaServerItem.setSendRtpPortRange(sendRtpPortRange); | ||
| 218 | mediaServerItem.setRecordAssistPort(recordAssistPort); | 207 | mediaServerItem.setRecordAssistPort(recordAssistPort); |
| 219 | - mediaServerItem.setHookAliveInterval(120); | 208 | + mediaServerItem.setHookAliveInterval(30.00f); |
| 220 | 209 | ||
| 221 | mediaServerItem.setCreateTime(DateUtil.getNow()); | 210 | mediaServerItem.setCreateTime(DateUtil.getNow()); |
| 222 | mediaServerItem.setUpdateTime(DateUtil.getNow()); | 211 | mediaServerItem.setUpdateTime(DateUtil.getNow()); |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
| @@ -8,14 +8,13 @@ import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | @@ -8,14 +8,13 @@ import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | ||
| 8 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | 8 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 9 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; | 9 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
| 10 | import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; | 10 | import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; |
| 11 | -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; | ||
| 12 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; | 11 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; |
| 13 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; | 12 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; |
| 14 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; | 13 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
| 15 | import com.genersoft.iot.vmp.gb28181.utils.SipUtils; | 14 | import com.genersoft.iot.vmp.gb28181.utils.SipUtils; |
| 16 | -import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; | ||
| 17 | import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager; | 15 | import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager; |
| 18 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; | 16 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
| 17 | +import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; | ||
| 19 | import com.genersoft.iot.vmp.media.zlm.dto.*; | 18 | import com.genersoft.iot.vmp.media.zlm.dto.*; |
| 20 | import com.genersoft.iot.vmp.service.IMediaServerService; | 19 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| 21 | import com.genersoft.iot.vmp.service.IPlayService; | 20 | import com.genersoft.iot.vmp.service.IPlayService; |
| @@ -39,9 +38,10 @@ import org.springframework.beans.factory.annotation.Autowired; | @@ -39,9 +38,10 @@ import org.springframework.beans.factory.annotation.Autowired; | ||
| 39 | import org.springframework.stereotype.Component; | 38 | import org.springframework.stereotype.Component; |
| 40 | 39 | ||
| 41 | import javax.sdp.*; | 40 | import javax.sdp.*; |
| 42 | -import javax.sip.*; | 41 | +import javax.sip.InvalidArgumentException; |
| 42 | +import javax.sip.RequestEvent; | ||
| 43 | +import javax.sip.SipException; | ||
| 43 | import javax.sip.header.CallIdHeader; | 44 | import javax.sip.header.CallIdHeader; |
| 44 | -import javax.sip.message.Request; | ||
| 45 | import javax.sip.message.Response; | 45 | import javax.sip.message.Response; |
| 46 | import java.text.ParseException; | 46 | import java.text.ParseException; |
| 47 | import java.time.Instant; | 47 | import java.time.Instant; |
| @@ -656,6 +656,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -656,6 +656,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 656 | if (!platform.isStartOfflinePush()) { | 656 | if (!platform.isStartOfflinePush()) { |
| 657 | // 平台设置中关闭了拉起离线的推流则直接回复 | 657 | // 平台设置中关闭了拉起离线的推流则直接回复 |
| 658 | try { | 658 | try { |
| 659 | + logger.info("[上级点播] 失败,推流设备未推流,channel: {}, app: {}, stream: {}", gbStream.getGbId(), gbStream.getApp(), gbStream.getStream()); | ||
| 659 | responseAck(request, Response.TEMPORARILY_UNAVAILABLE, "channel stream not pushing"); | 660 | responseAck(request, Response.TEMPORARILY_UNAVAILABLE, "channel stream not pushing"); |
| 660 | } catch (SipException | InvalidArgumentException | ParseException e) { | 661 | } catch (SipException | InvalidArgumentException | ParseException e) { |
| 661 | logger.error("[命令发送失败] invite 通道未推流: {}", e.getMessage()); | 662 | logger.error("[命令发送失败] invite 通道未推流: {}", e.getMessage()); |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
| @@ -85,7 +85,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen | @@ -85,7 +85,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen | ||
| 85 | String password = (device != null && !ObjectUtils.isEmpty(device.getPassword()))? device.getPassword() : sipConfig.getPassword(); | 85 | String password = (device != null && !ObjectUtils.isEmpty(device.getPassword()))? device.getPassword() : sipConfig.getPassword(); |
| 86 | AuthorizationHeader authHead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME); | 86 | AuthorizationHeader authHead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME); |
| 87 | if (authHead == null && !ObjectUtils.isEmpty(password)) { | 87 | if (authHead == null && !ObjectUtils.isEmpty(password)) { |
| 88 | - logger.info("[注册请求] 未携带授权头 回复401: {}", requestAddress); | 88 | + logger.info("[注册请求] 回复401: {}", requestAddress); |
| 89 | response = getMessageFactory().createResponse(Response.UNAUTHORIZED, request); | 89 | response = getMessageFactory().createResponse(Response.UNAUTHORIZED, request); |
| 90 | new DigestServerAuthenticationHelper().generateChallenge(getHeaderFactory(), response, sipConfig.getDomain()); | 90 | new DigestServerAuthenticationHelper().generateChallenge(getHeaderFactory(), response, sipConfig.getDomain()); |
| 91 | sipSender.transmitRequest(response); | 91 | sipSender.transmitRequest(response); |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
| 1 | package com.genersoft.iot.vmp.media.zlm; | 1 | package com.genersoft.iot.vmp.media.zlm; |
| 2 | 2 | ||
| 3 | -import java.text.ParseException; | ||
| 4 | -import java.util.HashMap; | ||
| 5 | -import java.util.List; | ||
| 6 | -import java.util.Map; | ||
| 7 | - | ||
| 8 | import com.alibaba.fastjson2.JSON; | 3 | import com.alibaba.fastjson2.JSON; |
| 4 | +import com.alibaba.fastjson2.JSONObject; | ||
| 9 | import com.genersoft.iot.vmp.common.StreamInfo; | 5 | import com.genersoft.iot.vmp.common.StreamInfo; |
| 10 | import com.genersoft.iot.vmp.conf.UserSetting; | 6 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 11 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | 7 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; |
| 12 | import com.genersoft.iot.vmp.gb28181.bean.*; | 8 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 13 | import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | 9 | import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
| 14 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | 10 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 11 | +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | ||
| 15 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; | 12 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; |
| 16 | -import com.genersoft.iot.vmp.media.zlm.dto.*; | 13 | +import com.genersoft.iot.vmp.media.zlm.dto.HookType; |
| 14 | +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | ||
| 15 | +import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; | ||
| 16 | +import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; | ||
| 17 | import com.genersoft.iot.vmp.media.zlm.dto.hook.*; | 17 | import com.genersoft.iot.vmp.media.zlm.dto.hook.*; |
| 18 | import com.genersoft.iot.vmp.service.*; | 18 | import com.genersoft.iot.vmp.service.*; |
| 19 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | 19 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| @@ -24,18 +24,15 @@ import org.springframework.beans.factory.annotation.Autowired; | @@ -24,18 +24,15 @@ import org.springframework.beans.factory.annotation.Autowired; | ||
| 24 | import org.springframework.beans.factory.annotation.Qualifier; | 24 | import org.springframework.beans.factory.annotation.Qualifier; |
| 25 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | 25 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; |
| 26 | import org.springframework.util.ObjectUtils; | 26 | import org.springframework.util.ObjectUtils; |
| 27 | -import org.springframework.web.bind.annotation.PostMapping; | ||
| 28 | -import org.springframework.web.bind.annotation.RequestBody; | ||
| 29 | -import org.springframework.web.bind.annotation.RequestMapping; | ||
| 30 | -import org.springframework.web.bind.annotation.ResponseBody; | ||
| 31 | -import org.springframework.web.bind.annotation.RestController; | ||
| 32 | - | ||
| 33 | -import com.alibaba.fastjson2.JSONObject; | ||
| 34 | -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | 27 | +import org.springframework.web.bind.annotation.*; |
| 35 | 28 | ||
| 36 | import javax.servlet.http.HttpServletRequest; | 29 | import javax.servlet.http.HttpServletRequest; |
| 37 | import javax.sip.InvalidArgumentException; | 30 | import javax.sip.InvalidArgumentException; |
| 38 | import javax.sip.SipException; | 31 | import javax.sip.SipException; |
| 32 | +import java.text.ParseException; | ||
| 33 | +import java.util.HashMap; | ||
| 34 | +import java.util.List; | ||
| 35 | +import java.util.Map; | ||
| 39 | 36 | ||
| 40 | /** | 37 | /** |
| 41 | * @description:针对 ZLMediaServer的hook事件监听 | 38 | * @description:针对 ZLMediaServer的hook事件监听 |
| @@ -571,6 +568,8 @@ public class ZLMHttpHookListener { | @@ -571,6 +568,8 @@ public class ZLMHttpHookListener { | ||
| 571 | public JSONObject onServerStarted(HttpServletRequest request, @RequestBody JSONObject jsonObject){ | 568 | public JSONObject onServerStarted(HttpServletRequest request, @RequestBody JSONObject jsonObject){ |
| 572 | 569 | ||
| 573 | jsonObject.put("ip", request.getRemoteAddr()); | 570 | jsonObject.put("ip", request.getRemoteAddr()); |
| 571 | + System.out.println(jsonObject.toJSONString() | ||
| 572 | + ); | ||
| 574 | ZLMServerConfig zlmServerConfig = JSON.to(ZLMServerConfig.class, jsonObject); | 573 | ZLMServerConfig zlmServerConfig = JSON.to(ZLMServerConfig.class, jsonObject); |
| 575 | zlmServerConfig.setIp(request.getRemoteAddr()); | 574 | zlmServerConfig.setIp(request.getRemoteAddr()); |
| 576 | logger.info("[ZLM HOOK] zlm 启动 " + zlmServerConfig.getGeneralMediaServerId()); | 575 | logger.info("[ZLM HOOK] zlm 启动 " + zlmServerConfig.getGeneralMediaServerId()); |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
| @@ -10,7 +10,6 @@ import org.slf4j.LoggerFactory; | @@ -10,7 +10,6 @@ import org.slf4j.LoggerFactory; | ||
| 10 | import org.springframework.beans.factory.annotation.Autowired; | 10 | import org.springframework.beans.factory.annotation.Autowired; |
| 11 | import org.springframework.stereotype.Component; | 11 | import org.springframework.stereotype.Component; |
| 12 | import org.springframework.util.ObjectUtils; | 12 | import org.springframework.util.ObjectUtils; |
| 13 | -import org.springframework.util.StringUtils; | ||
| 14 | 13 | ||
| 15 | import java.util.*; | 14 | import java.util.*; |
| 16 | 15 | ||
| @@ -294,7 +293,8 @@ public class ZLMRTPServerFactory { | @@ -294,7 +293,8 @@ public class ZLMRTPServerFactory { | ||
| 294 | */ | 293 | */ |
| 295 | public Boolean isStreamReady(MediaServerItem mediaServerItem, String app, String streamId) { | 294 | public Boolean isStreamReady(MediaServerItem mediaServerItem, String app, String streamId) { |
| 296 | JSONObject mediaInfo = zlmresTfulUtils.getMediaList(mediaServerItem, app, streamId); | 295 | JSONObject mediaInfo = zlmresTfulUtils.getMediaList(mediaServerItem, app, streamId); |
| 297 | - return (mediaInfo.getInteger("code") == 0 | 296 | + return mediaInfo != null && (mediaInfo.getInteger("code") == 0 |
| 297 | + | ||
| 298 | && mediaInfo.getJSONArray("data") != null | 298 | && mediaInfo.getJSONArray("data") != null |
| 299 | && mediaInfo.getJSONArray("data").size() > 0); | 299 | && mediaInfo.getJSONArray("data").size() > 0); |
| 300 | } | 300 | } |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerConfig.java
| @@ -66,7 +66,7 @@ public class ZLMServerConfig { | @@ -66,7 +66,7 @@ public class ZLMServerConfig { | ||
| 66 | private String hookAdminParams; | 66 | private String hookAdminParams; |
| 67 | 67 | ||
| 68 | @JSONField(name = "hook.alive_interval") | 68 | @JSONField(name = "hook.alive_interval") |
| 69 | - private int hookAliveInterval; | 69 | + private Float hookAliveInterval; |
| 70 | 70 | ||
| 71 | @JSONField(name = "hook.enable") | 71 | @JSONField(name = "hook.enable") |
| 72 | private String hookEnable; | 72 | private String hookEnable; |
| @@ -798,11 +798,11 @@ public class ZLMServerConfig { | @@ -798,11 +798,11 @@ public class ZLMServerConfig { | ||
| 798 | this.shellPhell = shellPhell; | 798 | this.shellPhell = shellPhell; |
| 799 | } | 799 | } |
| 800 | 800 | ||
| 801 | - public int getHookAliveInterval() { | 801 | + public Float getHookAliveInterval() { |
| 802 | return hookAliveInterval; | 802 | return hookAliveInterval; |
| 803 | } | 803 | } |
| 804 | 804 | ||
| 805 | - public void setHookAliveInterval(int hookAliveInterval) { | 805 | + public void setHookAliveInterval(Float hookAliveInterval) { |
| 806 | this.hookAliveInterval = hookAliveInterval; | 806 | this.hookAliveInterval = hookAliveInterval; |
| 807 | } | 807 | } |
| 808 | 808 |
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java
| @@ -5,7 +5,6 @@ import com.genersoft.iot.vmp.gb28181.session.SsrcConfig; | @@ -5,7 +5,6 @@ import com.genersoft.iot.vmp.gb28181.session.SsrcConfig; | ||
| 5 | import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; | 5 | import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; |
| 6 | import io.swagger.v3.oas.annotations.media.Schema; | 6 | import io.swagger.v3.oas.annotations.media.Schema; |
| 7 | import org.springframework.util.ObjectUtils; | 7 | import org.springframework.util.ObjectUtils; |
| 8 | -import org.springframework.util.StringUtils; | ||
| 9 | 8 | ||
| 10 | import java.util.HashMap; | 9 | import java.util.HashMap; |
| 11 | 10 | ||
| @@ -55,7 +54,7 @@ public class MediaServerItem{ | @@ -55,7 +54,7 @@ public class MediaServerItem{ | ||
| 55 | private String secret; | 54 | private String secret; |
| 56 | 55 | ||
| 57 | @Schema(description = "keepalive hook触发间隔,单位秒") | 56 | @Schema(description = "keepalive hook触发间隔,单位秒") |
| 58 | - private int hookAliveInterval; | 57 | + private Float hookAliveInterval; |
| 59 | 58 | ||
| 60 | @Schema(description = "是否使用多端口模式") | 59 | @Schema(description = "是否使用多端口模式") |
| 61 | private boolean rtpEnable; | 60 | private boolean rtpEnable; |
| @@ -332,11 +331,11 @@ public class MediaServerItem{ | @@ -332,11 +331,11 @@ public class MediaServerItem{ | ||
| 332 | this.sendRtpPortRange = sendRtpPortRange; | 331 | this.sendRtpPortRange = sendRtpPortRange; |
| 333 | } | 332 | } |
| 334 | 333 | ||
| 335 | - public int getHookAliveInterval() { | 334 | + public Float getHookAliveInterval() { |
| 336 | return hookAliveInterval; | 335 | return hookAliveInterval; |
| 337 | } | 336 | } |
| 338 | 337 | ||
| 339 | - public void setHookAliveInterval(int hookAliveInterval) { | 338 | + public void setHookAliveInterval(Float hookAliveInterval) { |
| 340 | this.hookAliveInterval = hookAliveInterval; | 339 | this.hookAliveInterval = hookAliveInterval; |
| 341 | } | 340 | } |
| 342 | } | 341 | } |
src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java
| @@ -11,6 +11,9 @@ import com.github.pagehelper.PageInfo; | @@ -11,6 +11,9 @@ import com.github.pagehelper.PageInfo; | ||
| 11 | import java.util.List; | 11 | import java.util.List; |
| 12 | import java.util.Map; | 12 | import java.util.Map; |
| 13 | 13 | ||
| 14 | +/** | ||
| 15 | + * @author lin | ||
| 16 | + */ | ||
| 14 | public interface IStreamPushService { | 17 | public interface IStreamPushService { |
| 15 | 18 | ||
| 16 | List<StreamPushItem> handleJSON(String json, MediaServerItem mediaServerItem); | 19 | List<StreamPushItem> handleJSON(String json, MediaServerItem mediaServerItem); |
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
| 1 | package com.genersoft.iot.vmp.service.impl; | 1 | package com.genersoft.iot.vmp.service.impl; |
| 2 | 2 | ||
| 3 | -import java.time.LocalDateTime; | ||
| 4 | -import java.util.ArrayList; | ||
| 5 | -import java.util.Collections; | ||
| 6 | -import java.util.HashMap; | ||
| 7 | -import java.util.List; | ||
| 8 | -import java.util.Map; | ||
| 9 | -import java.util.Set; | ||
| 10 | - | ||
| 11 | -import com.genersoft.iot.vmp.conf.DynamicTask; | ||
| 12 | -import com.genersoft.iot.vmp.conf.exception.ControllerException; | ||
| 13 | -import com.genersoft.iot.vmp.media.zlm.dto.ServerKeepaliveData; | ||
| 14 | -import com.genersoft.iot.vmp.service.bean.MediaServerLoad; | ||
| 15 | -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | ||
| 16 | -import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; | ||
| 17 | -import org.slf4j.Logger; | ||
| 18 | -import org.slf4j.LoggerFactory; | ||
| 19 | -import org.springframework.beans.factory.annotation.Autowired; | ||
| 20 | -import org.springframework.beans.factory.annotation.Value; | ||
| 21 | -import org.springframework.jdbc.datasource.DataSourceTransactionManager; | ||
| 22 | -import org.springframework.stereotype.Service; | ||
| 23 | -import org.springframework.transaction.TransactionDefinition; | ||
| 24 | -import org.springframework.transaction.TransactionStatus; | ||
| 25 | -import org.springframework.util.ObjectUtils; | ||
| 26 | - | ||
| 27 | import com.alibaba.fastjson2.JSON; | 3 | import com.alibaba.fastjson2.JSON; |
| 28 | import com.alibaba.fastjson2.JSONArray; | 4 | import com.alibaba.fastjson2.JSONArray; |
| 29 | import com.alibaba.fastjson2.JSONObject; | 5 | import com.alibaba.fastjson2.JSONObject; |
| 30 | import com.genersoft.iot.vmp.common.VideoManagerConstants; | 6 | import com.genersoft.iot.vmp.common.VideoManagerConstants; |
| 7 | +import com.genersoft.iot.vmp.conf.DynamicTask; | ||
| 31 | import com.genersoft.iot.vmp.conf.SipConfig; | 8 | import com.genersoft.iot.vmp.conf.SipConfig; |
| 32 | import com.genersoft.iot.vmp.conf.UserSetting; | 9 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 10 | +import com.genersoft.iot.vmp.conf.exception.ControllerException; | ||
| 33 | import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | 11 | import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
| 34 | import com.genersoft.iot.vmp.gb28181.session.SsrcConfig; | 12 | import com.genersoft.iot.vmp.gb28181.session.SsrcConfig; |
| 35 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | 13 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| @@ -37,15 +15,30 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; | @@ -37,15 +15,30 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; | ||
| 37 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; | 15 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
| 38 | import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; | 16 | import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; |
| 39 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | 17 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 18 | +import com.genersoft.iot.vmp.media.zlm.dto.ServerKeepaliveData; | ||
| 40 | import com.genersoft.iot.vmp.service.IMediaServerService; | 19 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| 20 | +import com.genersoft.iot.vmp.service.bean.MediaServerLoad; | ||
| 41 | import com.genersoft.iot.vmp.service.bean.SSRCInfo; | 21 | import com.genersoft.iot.vmp.service.bean.SSRCInfo; |
| 22 | +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | ||
| 42 | import com.genersoft.iot.vmp.storager.dao.MediaServerMapper; | 23 | import com.genersoft.iot.vmp.storager.dao.MediaServerMapper; |
| 43 | import com.genersoft.iot.vmp.utils.DateUtil; | 24 | import com.genersoft.iot.vmp.utils.DateUtil; |
| 44 | import com.genersoft.iot.vmp.utils.redis.RedisUtil; | 25 | import com.genersoft.iot.vmp.utils.redis.RedisUtil; |
| 45 | - | 26 | +import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; |
| 46 | import okhttp3.OkHttpClient; | 27 | import okhttp3.OkHttpClient; |
| 47 | import okhttp3.Request; | 28 | import okhttp3.Request; |
| 48 | import okhttp3.Response; | 29 | import okhttp3.Response; |
| 30 | +import org.slf4j.Logger; | ||
| 31 | +import org.slf4j.LoggerFactory; | ||
| 32 | +import org.springframework.beans.factory.annotation.Autowired; | ||
| 33 | +import org.springframework.beans.factory.annotation.Value; | ||
| 34 | +import org.springframework.jdbc.datasource.DataSourceTransactionManager; | ||
| 35 | +import org.springframework.stereotype.Service; | ||
| 36 | +import org.springframework.transaction.TransactionDefinition; | ||
| 37 | +import org.springframework.transaction.TransactionStatus; | ||
| 38 | +import org.springframework.util.ObjectUtils; | ||
| 39 | + | ||
| 40 | +import java.time.LocalDateTime; | ||
| 41 | +import java.util.*; | ||
| 49 | 42 | ||
| 50 | /** | 43 | /** |
| 51 | * 媒体服务器节点管理 | 44 | * 媒体服务器节点管理 |
| @@ -129,6 +122,7 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -129,6 +122,7 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 129 | @Override | 122 | @Override |
| 130 | public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String presetSsrc, boolean ssrcCheck, boolean isPlayback, Integer port) { | 123 | public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String presetSsrc, boolean ssrcCheck, boolean isPlayback, Integer port) { |
| 131 | if (mediaServerItem == null || mediaServerItem.getId() == null) { | 124 | if (mediaServerItem == null || mediaServerItem.getId() == null) { |
| 125 | + logger.info("[openRTPServer] 失败, mediaServerItem == null || mediaServerItem.getId() == null"); | ||
| 132 | return null; | 126 | return null; |
| 133 | } | 127 | } |
| 134 | // 获取mediaServer可用的ssrc | 128 | // 获取mediaServer可用的ssrc |
| @@ -306,7 +300,7 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -306,7 +300,7 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 306 | public void add(MediaServerItem mediaServerItem) { | 300 | public void add(MediaServerItem mediaServerItem) { |
| 307 | mediaServerItem.setCreateTime(DateUtil.getNow()); | 301 | mediaServerItem.setCreateTime(DateUtil.getNow()); |
| 308 | mediaServerItem.setUpdateTime(DateUtil.getNow()); | 302 | mediaServerItem.setUpdateTime(DateUtil.getNow()); |
| 309 | - mediaServerItem.setHookAliveInterval(120); | 303 | + mediaServerItem.setHookAliveInterval(30f); |
| 310 | JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem); | 304 | JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem); |
| 311 | if (responseJSON != null) { | 305 | if (responseJSON != null) { |
| 312 | JSONArray data = responseJSON.getJSONArray("data"); | 306 | JSONArray data = responseJSON.getJSONArray("data"); |
| @@ -413,7 +407,7 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -413,7 +407,7 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 413 | } | 407 | } |
| 414 | final String zlmKeepaliveKey = zlmKeepaliveKeyPrefix + serverItem.getId(); | 408 | final String zlmKeepaliveKey = zlmKeepaliveKeyPrefix + serverItem.getId(); |
| 415 | dynamicTask.stop(zlmKeepaliveKey); | 409 | dynamicTask.stop(zlmKeepaliveKey); |
| 416 | - dynamicTask.startDelay(zlmKeepaliveKey, new KeepAliveTimeoutRunnable(serverItem), (serverItem.getHookAliveInterval() + 5) * 1000); | 410 | + dynamicTask.startDelay(zlmKeepaliveKey, new KeepAliveTimeoutRunnable(serverItem), (Math.getExponent(serverItem.getHookAliveInterval()) + 5) * 1000); |
| 417 | publisher.zlmOnlineEventPublish(serverItem.getId()); | 411 | publisher.zlmOnlineEventPublish(serverItem.getId()); |
| 418 | logger.info("[ZLM] 连接成功 {} - {}:{} ", | 412 | logger.info("[ZLM] 连接成功 {} - {}:{} ", |
| 419 | zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort()); | 413 | zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort()); |
| @@ -666,7 +660,7 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -666,7 +660,7 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 666 | } | 660 | } |
| 667 | final String zlmKeepaliveKey = zlmKeepaliveKeyPrefix + mediaServerItem.getId(); | 661 | final String zlmKeepaliveKey = zlmKeepaliveKeyPrefix + mediaServerItem.getId(); |
| 668 | dynamicTask.stop(zlmKeepaliveKey); | 662 | dynamicTask.stop(zlmKeepaliveKey); |
| 669 | - dynamicTask.startDelay(zlmKeepaliveKey, new KeepAliveTimeoutRunnable(mediaServerItem), (mediaServerItem.getHookAliveInterval() + 5) * 1000); | 663 | + dynamicTask.startDelay(zlmKeepaliveKey, new KeepAliveTimeoutRunnable(mediaServerItem), (mediaServerItem.getHookAliveInterval().intValue() + 5) * 1000); |
| 670 | } | 664 | } |
| 671 | 665 | ||
| 672 | private MediaServerItem getOneFromDatabase(String mediaServerId) { | 666 | private MediaServerItem getOneFromDatabase(String mediaServerId) { |
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
| 1 | package com.genersoft.iot.vmp.service.impl; | 1 | package com.genersoft.iot.vmp.service.impl; |
| 2 | 2 | ||
| 3 | -import java.math.BigDecimal; | ||
| 4 | -import java.math.RoundingMode; | ||
| 5 | -import java.text.ParseException; | ||
| 6 | -import java.util.*; | ||
| 7 | - | ||
| 8 | -import javax.sip.InvalidArgumentException; | ||
| 9 | -import javax.sip.ResponseEvent; | ||
| 10 | -import javax.sip.SipException; | ||
| 11 | - | ||
| 12 | -import com.genersoft.iot.vmp.conf.exception.ControllerException; | ||
| 13 | -import com.genersoft.iot.vmp.conf.exception.ServiceException; | ||
| 14 | -import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | ||
| 15 | -import com.genersoft.iot.vmp.gb28181.bean.*; | ||
| 16 | -import com.genersoft.iot.vmp.service.IDeviceService; | ||
| 17 | -import com.genersoft.iot.vmp.utils.redis.RedisUtil; | ||
| 18 | -import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; | ||
| 19 | -import org.slf4j.Logger; | ||
| 20 | -import org.slf4j.LoggerFactory; | ||
| 21 | -import org.springframework.beans.factory.annotation.Autowired; | ||
| 22 | -import org.springframework.beans.factory.annotation.Qualifier; | ||
| 23 | -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | ||
| 24 | -import org.springframework.stereotype.Service; | ||
| 25 | -import org.springframework.util.ObjectUtils; | ||
| 26 | -import org.springframework.web.context.request.async.DeferredResult; | ||
| 27 | - | ||
| 28 | import com.alibaba.fastjson2.JSON; | 3 | import com.alibaba.fastjson2.JSON; |
| 29 | import com.alibaba.fastjson2.JSONArray; | 4 | import com.alibaba.fastjson2.JSONArray; |
| 30 | import com.alibaba.fastjson2.JSONObject; | 5 | import com.alibaba.fastjson2.JSONObject; |
| 31 | import com.genersoft.iot.vmp.common.StreamInfo; | 6 | import com.genersoft.iot.vmp.common.StreamInfo; |
| 32 | import com.genersoft.iot.vmp.conf.DynamicTask; | 7 | import com.genersoft.iot.vmp.conf.DynamicTask; |
| 33 | import com.genersoft.iot.vmp.conf.UserSetting; | 8 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 9 | +import com.genersoft.iot.vmp.conf.exception.ControllerException; | ||
| 10 | +import com.genersoft.iot.vmp.conf.exception.ServiceException; | ||
| 11 | +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | ||
| 12 | +import com.genersoft.iot.vmp.gb28181.bean.*; | ||
| 34 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | 13 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| 35 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | 14 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 36 | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; | 15 | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
| 37 | import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | 16 | import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; |
| 38 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | 17 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; |
| 39 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; | 18 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; |
| 40 | -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; | ||
| 41 | -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; | ||
| 42 | -import com.genersoft.iot.vmp.utils.DateUtil; | ||
| 43 | import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils; | 19 | import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils; |
| 44 | -import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; | ||
| 45 | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; | 20 | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; |
| 21 | +import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; | ||
| 22 | +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; | ||
| 23 | +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; | ||
| 46 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | 24 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 25 | +import com.genersoft.iot.vmp.service.IDeviceService; | ||
| 47 | import com.genersoft.iot.vmp.service.IMediaServerService; | 26 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| 48 | import com.genersoft.iot.vmp.service.IMediaService; | 27 | import com.genersoft.iot.vmp.service.IMediaService; |
| 49 | import com.genersoft.iot.vmp.service.IPlayService; | 28 | import com.genersoft.iot.vmp.service.IPlayService; |
| @@ -53,8 +32,29 @@ import com.genersoft.iot.vmp.service.bean.PlayBackResult; | @@ -53,8 +32,29 @@ import com.genersoft.iot.vmp.service.bean.PlayBackResult; | ||
| 53 | import com.genersoft.iot.vmp.service.bean.SSRCInfo; | 32 | import com.genersoft.iot.vmp.service.bean.SSRCInfo; |
| 54 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | 33 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 55 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | 34 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 35 | +import com.genersoft.iot.vmp.utils.DateUtil; | ||
| 36 | +import com.genersoft.iot.vmp.utils.redis.RedisUtil; | ||
| 37 | +import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; | ||
| 56 | import com.genersoft.iot.vmp.vmanager.bean.WVPResult; | 38 | import com.genersoft.iot.vmp.vmanager.bean.WVPResult; |
| 57 | import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; | 39 | import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; |
| 40 | +import org.slf4j.Logger; | ||
| 41 | +import org.slf4j.LoggerFactory; | ||
| 42 | +import org.springframework.beans.factory.annotation.Autowired; | ||
| 43 | +import org.springframework.beans.factory.annotation.Qualifier; | ||
| 44 | +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | ||
| 45 | +import org.springframework.stereotype.Service; | ||
| 46 | +import org.springframework.util.ObjectUtils; | ||
| 47 | +import org.springframework.web.context.request.async.DeferredResult; | ||
| 48 | + | ||
| 49 | +import javax.sip.InvalidArgumentException; | ||
| 50 | +import javax.sip.ResponseEvent; | ||
| 51 | +import javax.sip.SipException; | ||
| 52 | +import java.math.BigDecimal; | ||
| 53 | +import java.math.RoundingMode; | ||
| 54 | +import java.text.ParseException; | ||
| 55 | +import java.util.List; | ||
| 56 | +import java.util.Objects; | ||
| 57 | +import java.util.UUID; | ||
| 58 | 58 | ||
| 59 | @SuppressWarnings(value = {"rawtypes", "unchecked"}) | 59 | @SuppressWarnings(value = {"rawtypes", "unchecked"}) |
| 60 | @Service | 60 | @Service |
| @@ -212,6 +212,15 @@ public class PlayServiceImpl implements IPlayService { | @@ -212,6 +212,15 @@ public class PlayServiceImpl implements IPlayService { | ||
| 212 | } | 212 | } |
| 213 | SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, device.isSsrcCheck(), false); | 213 | SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, device.isSsrcCheck(), false); |
| 214 | logger.info(JSONObject.toJSONString(ssrcInfo)); | 214 | logger.info(JSONObject.toJSONString(ssrcInfo)); |
| 215 | + if (ssrcInfo == null) { | ||
| 216 | + WVPResult wvpResult = new WVPResult(); | ||
| 217 | + wvpResult.setCode(ErrorCode.ERROR100.getCode()); | ||
| 218 | + wvpResult.setMsg("开启收流失败"); | ||
| 219 | + msg.setData(wvpResult); | ||
| 220 | + | ||
| 221 | + resultHolder.invokeAllResult(msg); | ||
| 222 | + return playResult; | ||
| 223 | + } | ||
| 215 | play(mediaServerItem, ssrcInfo, device, channelId, (mediaServerItemInUse, response) -> { | 224 | play(mediaServerItem, ssrcInfo, device, channelId, (mediaServerItemInUse, response) -> { |
| 216 | if (hookEvent != null) { | 225 | if (hookEvent != null) { |
| 217 | hookEvent.response(mediaServerItem, response); | 226 | hookEvent.response(mediaServerItem, response); |
| @@ -249,45 +258,33 @@ public class PlayServiceImpl implements IPlayService { | @@ -249,45 +258,33 @@ public class PlayServiceImpl implements IPlayService { | ||
| 249 | ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, | 258 | ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, |
| 250 | InviteTimeOutCallback timeoutCallback, String uuid) { | 259 | InviteTimeOutCallback timeoutCallback, String uuid) { |
| 251 | 260 | ||
| 252 | - String streamId = null; | ||
| 253 | - if (mediaServerItem.isRtpEnable()) { | ||
| 254 | - streamId = String.format("%s_%s", device.getDeviceId(), channelId); | ||
| 255 | - } | ||
| 256 | - if (ssrcInfo == null) { | ||
| 257 | - ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, device.isSsrcCheck(), false); | ||
| 258 | - } | ||
| 259 | logger.info("[点播开始] deviceId: {}, channelId: {},收流端口: {}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, ssrcInfo.getPort(), device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); | 261 | logger.info("[点播开始] deviceId: {}, channelId: {},收流端口: {}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, ssrcInfo.getPort(), device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); |
| 260 | // 超时处理 | 262 | // 超时处理 |
| 261 | String timeOutTaskKey = UUID.randomUUID().toString(); | 263 | String timeOutTaskKey = UUID.randomUUID().toString(); |
| 262 | - SSRCInfo finalSsrcInfo = ssrcInfo; | ||
| 263 | dynamicTask.startDelay(timeOutTaskKey, () -> { | 264 | dynamicTask.startDelay(timeOutTaskKey, () -> { |
| 264 | - | ||
| 265 | - logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},端口:{}, SSRC: {}", device.getDeviceId(), channelId, finalSsrcInfo.getPort(), finalSsrcInfo.getSsrc()); | ||
| 266 | - timeoutCallback.run(1, "收流超时"); | ||
| 267 | - // 点播超时回复BYE 同时释放ssrc以及此次点播的资源 | ||
| 268 | - try { | ||
| 269 | - cmder.streamByeCmd(device, channelId, finalSsrcInfo.getStream(), null); | ||
| 270 | - } catch (InvalidArgumentException | ParseException | SipException e) { | ||
| 271 | - logger.error("[点播超时], 发送BYE失败 {}", e.getMessage()); | ||
| 272 | - } catch (SsrcTransactionNotFoundException e) { | ||
| 273 | - timeoutCallback.run(0, "点播超时"); | ||
| 274 | - mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc()); | ||
| 275 | - mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream()); | ||
| 276 | - streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream()); | 265 | + // 执行超时任务时查询是否已经成功,成功了则不执行超时任务,防止超时任务取消失败的情况 |
| 266 | + if (redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId) == null) { | ||
| 267 | + logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},端口:{}, SSRC: {}", device.getDeviceId(), channelId, ssrcInfo.getPort(), ssrcInfo.getSsrc()); | ||
| 268 | + // 点播超时回复BYE 同时释放ssrc以及此次点播的资源 | ||
| 269 | + try { | ||
| 270 | + cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null); | ||
| 271 | + } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) { | ||
| 272 | + logger.error("[点播超时], 发送BYE失败 {}", e.getMessage()); | ||
| 273 | + } finally { | ||
| 274 | + timeoutCallback.run(1, "收流超时"); | ||
| 275 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | ||
| 276 | + mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); | ||
| 277 | + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); | ||
| 278 | + mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); | ||
| 279 | + } | ||
| 277 | } | 280 | } |
| 278 | }, userSetting.getPlayTimeout()); | 281 | }, userSetting.getPlayTimeout()); |
| 279 | - final String ssrc = ssrcInfo.getSsrc(); | ||
| 280 | - final String stream = ssrcInfo.getStream(); | ||
| 281 | - //端口获取失败的ssrcInfo 没有必要发送点播指令 | ||
| 282 | - if (ssrcInfo.getPort() <= 0) { | ||
| 283 | - logger.info("[点播端口分配异常],deviceId={},channelId={},ssrcInfo={}", device.getDeviceId(), channelId, ssrcInfo); | ||
| 284 | - return; | ||
| 285 | - } | 282 | + |
| 286 | try { | 283 | try { |
| 287 | cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> { | 284 | cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> { |
| 288 | logger.info("收到订阅消息: " + response.toJSONString()); | 285 | logger.info("收到订阅消息: " + response.toJSONString()); |
| 289 | System.out.println("停止超时任务: " + timeOutTaskKey); | 286 | System.out.println("停止超时任务: " + timeOutTaskKey); |
| 290 | - dynamicTask.stop(timeOutTaskKey); | 287 | + |
| 291 | // hook响应 | 288 | // hook响应 |
| 292 | onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId, uuid); | 289 | onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId, uuid); |
| 293 | hookEvent.response(mediaServerItemInuse, response); | 290 | hookEvent.response(mediaServerItemInuse, response); |
| @@ -303,18 +300,18 @@ public class PlayServiceImpl implements IPlayService { | @@ -303,18 +300,18 @@ public class PlayServiceImpl implements IPlayService { | ||
| 303 | //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 TODO 后续对不规范的非10位ssrc兼容 | 300 | //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 TODO 后续对不规范的非10位ssrc兼容 |
| 304 | String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); | 301 | String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); |
| 305 | // 查询到ssrc不一致且开启了ssrc校验则需要针对处理 | 302 | // 查询到ssrc不一致且开启了ssrc校验则需要针对处理 |
| 306 | - if (ssrc.equals(ssrcInResponse)) { | 303 | + if (ssrcInfo.getSsrc().equals(ssrcInResponse)) { |
| 307 | return; | 304 | return; |
| 308 | } | 305 | } |
| 309 | logger.info("[点播消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse); | 306 | logger.info("[点播消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse); |
| 310 | if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { | 307 | if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { |
| 311 | - logger.info("[点播消息] SSRC修正 {}->{}", ssrc, ssrcInResponse); | 308 | + logger.info("[点播消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); |
| 312 | 309 | ||
| 313 | if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) { | 310 | if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) { |
| 314 | // ssrc 不可用 | 311 | // ssrc 不可用 |
| 315 | // 释放ssrc | 312 | // 释放ssrc |
| 316 | - mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc()); | ||
| 317 | - streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream()); | 313 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); |
| 314 | + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); | ||
| 318 | event.msg = "下级自定义了ssrc,但是此ssrc不可用"; | 315 | event.msg = "下级自定义了ssrc,但是此ssrc不可用"; |
| 319 | event.statusCode = 400; | 316 | event.statusCode = 400; |
| 320 | errorEvent.response(event); | 317 | errorEvent.response(event); |
| @@ -324,7 +321,7 @@ public class PlayServiceImpl implements IPlayService { | @@ -324,7 +321,7 @@ public class PlayServiceImpl implements IPlayService { | ||
| 324 | // 单端口模式streamId也有变化,需要重新设置监听 | 321 | // 单端口模式streamId也有变化,需要重新设置监听 |
| 325 | if (!mediaServerItem.isRtpEnable()) { | 322 | if (!mediaServerItem.isRtpEnable()) { |
| 326 | // 添加订阅 | 323 | // 添加订阅 |
| 327 | - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId()); | 324 | + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId()); |
| 328 | subscribe.removeSubscribe(hookSubscribe); | 325 | subscribe.removeSubscribe(hookSubscribe); |
| 329 | hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase()); | 326 | hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase()); |
| 330 | subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response) -> { | 327 | subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response) -> { |
| @@ -336,30 +333,30 @@ public class PlayServiceImpl implements IPlayService { | @@ -336,30 +333,30 @@ public class PlayServiceImpl implements IPlayService { | ||
| 336 | }); | 333 | }); |
| 337 | } | 334 | } |
| 338 | // 关闭rtp server | 335 | // 关闭rtp server |
| 339 | - mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream()); | 336 | + mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); |
| 340 | // 重新开启ssrc server | 337 | // 重新开启ssrc server |
| 341 | - mediaServerService.openRTPServer(mediaServerItem, finalSsrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), false, finalSsrcInfo.getPort()); | 338 | + mediaServerService.openRTPServer(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), false, ssrcInfo.getPort()); |
| 342 | 339 | ||
| 343 | } | 340 | } |
| 344 | } | 341 | } |
| 345 | }, (event) -> { | 342 | }, (event) -> { |
| 346 | dynamicTask.stop(timeOutTaskKey); | 343 | dynamicTask.stop(timeOutTaskKey); |
| 347 | - mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream()); | 344 | + mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); |
| 348 | // 释放ssrc | 345 | // 释放ssrc |
| 349 | - mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc()); | 346 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); |
| 350 | 347 | ||
| 351 | - streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream()); | 348 | + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); |
| 352 | errorEvent.response(event); | 349 | errorEvent.response(event); |
| 353 | }); | 350 | }); |
| 354 | } catch (InvalidArgumentException | SipException | ParseException e) { | 351 | } catch (InvalidArgumentException | SipException | ParseException e) { |
| 355 | 352 | ||
| 356 | logger.error("[命令发送失败] 点播消息: {}", e.getMessage()); | 353 | logger.error("[命令发送失败] 点播消息: {}", e.getMessage()); |
| 357 | dynamicTask.stop(timeOutTaskKey); | 354 | dynamicTask.stop(timeOutTaskKey); |
| 358 | - mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream()); | 355 | + mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); |
| 359 | // 释放ssrc | 356 | // 释放ssrc |
| 360 | - mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc()); | 357 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); |
| 361 | 358 | ||
| 362 | - streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream()); | 359 | + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); |
| 363 | SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new CmdSendFailEvent(null)); | 360 | SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new CmdSendFailEvent(null)); |
| 364 | eventResult.msg = "命令发送失败"; | 361 | eventResult.msg = "命令发送失败"; |
| 365 | errorEvent.response(eventResult); | 362 | errorEvent.response(eventResult); |
src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformGbStreamMapper.java
| @@ -23,10 +23,10 @@ public interface PlatformGbStreamMapper { | @@ -23,10 +23,10 @@ public interface PlatformGbStreamMapper { | ||
| 23 | 23 | ||
| 24 | @Insert("<script> " + | 24 | @Insert("<script> " + |
| 25 | "INSERT into platform_gb_stream " + | 25 | "INSERT into platform_gb_stream " + |
| 26 | - "(gbStreamId, platformId, catalogId,status) " + | 26 | + "(gbStreamId, platformId, catalogId) " + |
| 27 | "values " + | 27 | "values " + |
| 28 | "<foreach collection='streamPushItems' index='index' item='item' separator=','> " + | 28 | "<foreach collection='streamPushItems' index='index' item='item' separator=','> " + |
| 29 | - "(${item.gbStreamId}, '${item.platformId}', '${item.catalogId}'), '${item.status}')" + | 29 | + "(${item.gbStreamId}, '${item.platformId}', '${item.catalogId}')" + |
| 30 | "</foreach> " + | 30 | "</foreach> " + |
| 31 | "</script>") | 31 | "</script>") |
| 32 | int batchAdd(List<StreamPushItem> streamPushItems); | 32 | int batchAdd(List<StreamPushItem> streamPushItems); |