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