Commit 2466a248609b2a9b8eeee08c1378b2a440db475d

Authored by 648540858
1 parent c62a8986

去除发送流端口范围

... ... @@ -11,7 +11,7 @@
11 11  
12 12 <groupId>com.genersoft</groupId>
13 13 <artifactId>wvp-pro</artifactId>
14   - <version>2.3.2</version>
  14 + <version>2.6.6</version>
15 15 <name>web video platform</name>
16 16 <description>国标28181视频平台</description>
17 17  
... ...
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);
... ...