Commit 7d3cbb8253ec3dc7f4004ae67371f852727909df

Authored by 648540858
2 parents 19c99677 d48f89ee

Merge branch 'wvp-28181-2.0' into main-dev

README.md
@@ -107,6 +107,10 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git @@ -107,6 +107,10 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git
107 - [X] 支持Mysql,Postgresql,金仓等数据库 107 - [X] 支持Mysql,Postgresql,金仓等数据库
108 - [X] 支持Onvif(目前在onvif分支,需要安装onvif服务,服务请在知识星球获取) 108 - [X] 支持Onvif(目前在onvif分支,需要安装onvif服务,服务请在知识星球获取)
109 109
  110 +# 非开源的内容
  111 +- [X] ONVIF设备的接入,支持点播,云台控制,国标级联点播,自动点播。在[知识星球](https://t.zsxq.com/10WAnH2MP)放了试用安装包以及使用教程,没有使用时间限制,需要源码可以星球私信我或者邮箱联系。
  112 +
  113 +
110 # 授权协议 114 # 授权协议
111 本项目自有代码使用宽松的MIT协议,在保留版权信息的情况下可以自由应用于各自商用、非商业的项目。 但是本项目也零碎的使用了一些其他的开源代码,在商用的情况下请自行替代或剔除; 由于使用本项目而产生的商业纠纷或侵权行为一概与本项目及开发者无关,请自行承担法律风险。 在使用本项目代码时,也应该在授权协议中同时表明本项目依赖的第三方库的协议 115 本项目自有代码使用宽松的MIT协议,在保留版权信息的情况下可以自由应用于各自商用、非商业的项目。 但是本项目也零碎的使用了一些其他的开源代码,在商用的情况下请自行替代或剔除; 由于使用本项目而产生的商业纠纷或侵权行为一概与本项目及开发者无关,请自行承担法律风险。 在使用本项目代码时,也应该在授权协议中同时表明本项目依赖的第三方库的协议
112 116
src/main/java/com/genersoft/iot/vmp/common/CommonGbChannel.java 0 → 100644
  1 +package com.genersoft.iot.vmp.common;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +
  5 +public class CommonGbChannel {
  6 +
  7 + /**
  8 + * 国标字段:归属
  9 + */
  10 + @Schema(description = "归属")
  11 + private String owner;
  12 +
  13 + /**
  14 + * 国标字段:行政区划
  15 + */
  16 + @Schema(description = "行政区划")
  17 + private String civilCode;
  18 +
  19 + /**
  20 + * 国标字段:安装地址
  21 + */
  22 + @Schema(description = "安装地址")
  23 + private String address;
  24 +
  25 + /**
  26 + * 国标字段:经度
  27 + */
  28 + @Schema(description = "经度")
  29 + private Double longitude;
  30 +
  31 + /**
  32 + * 国标字段:纬度
  33 + */
  34 + @Schema(description = "纬度")
  35 + private Double latitude;
  36 +
  37 + /**
  38 + * 国标字段:摄像机类型:
  39 + * 1-球机;
  40 + * 2-半球;
  41 + * 3-固定枪机;
  42 + * 4-遥控枪机
  43 + */
  44 + @Schema(description = "摄像机类型")
  45 + private Integer ptzType;
  46 +
  47 + /**
  48 + * 国标字段:摄像机位置类型扩展。
  49 + * 1-省际检查站、
  50 + * 2-党政机关、
  51 + * 3-车站码头、
  52 + * 4-中心广场、
  53 + * 5-体育场馆、
  54 + * 6-商业中心、
  55 + * 7-宗教场所、
  56 + * 8-校园周边、
  57 + * 9-治安复杂区域、
  58 + * 10-交通干线
  59 + */
  60 + @Schema(description = "摄像机位置类型扩展")
  61 + private Integer positionType;
  62 +
  63 + /**
  64 + * 国标字段:安装位置室外、室内属性
  65 + * 1-室外、
  66 + * 2-室内
  67 + */
  68 + @Schema(description = "安装位置室外、室内属性")
  69 + private Integer roomType;
  70 +
  71 + /**
  72 + * 国标字段:用途
  73 + * 1-治安、
  74 + * 2-交通、
  75 + * 3-重点、
  76 + */
  77 + @Schema(description = "用途")
  78 + private Integer useType;
  79 +
  80 + /**
  81 + * 国标字段:补光属性
  82 + * 1-无补光、
  83 + * 2-红外补光、
  84 + * 3-白光补光
  85 + */
  86 + @Schema(description = "补光属性")
  87 + private Integer supplyLightType;
  88 +
  89 + /**
  90 + * 摄像机监视方位属性。
  91 + * 1-东、
  92 + * 2-西、
  93 + * 3-南、
  94 + * 4-北、
  95 + * 5-东南、
  96 + * 6-东北、
  97 + * 7-西南、
  98 + * 8-西北
  99 + *
  100 + */
  101 + @Schema(description = "方位")
  102 + private Integer directionType;
  103 +
  104 + public String getOwner() {
  105 + return owner;
  106 + }
  107 +
  108 + public void setOwner(String owner) {
  109 + this.owner = owner;
  110 + }
  111 +
  112 + public String getCivilCode() {
  113 + return civilCode;
  114 + }
  115 +
  116 + public void setCivilCode(String civilCode) {
  117 + this.civilCode = civilCode;
  118 + }
  119 +
  120 + public String getAddress() {
  121 + return address;
  122 + }
  123 +
  124 + public void setAddress(String address) {
  125 + this.address = address;
  126 + }
  127 +
  128 + public Double getLongitude() {
  129 + return longitude;
  130 + }
  131 +
  132 + public void setLongitude(Double longitude) {
  133 + this.longitude = longitude;
  134 + }
  135 +
  136 + public Double getLatitude() {
  137 + return latitude;
  138 + }
  139 +
  140 + public void setLatitude(Double latitude) {
  141 + this.latitude = latitude;
  142 + }
  143 +
  144 + public Integer getPtzType() {
  145 + return ptzType;
  146 + }
  147 +
  148 + public void setPtzType(Integer ptzType) {
  149 + this.ptzType = ptzType;
  150 + }
  151 +
  152 + public Integer getPositionType() {
  153 + return positionType;
  154 + }
  155 +
  156 + public void setPositionType(Integer positionType) {
  157 + this.positionType = positionType;
  158 + }
  159 +
  160 + public Integer getRoomType() {
  161 + return roomType;
  162 + }
  163 +
  164 + public void setRoomType(Integer roomType) {
  165 + this.roomType = roomType;
  166 + }
  167 +
  168 + public Integer getUseType() {
  169 + return useType;
  170 + }
  171 +
  172 + public void setUseType(Integer useType) {
  173 + this.useType = useType;
  174 + }
  175 +
  176 + public Integer getSupplyLightType() {
  177 + return supplyLightType;
  178 + }
  179 +
  180 + public void setSupplyLightType(Integer supplyLightType) {
  181 + this.supplyLightType = supplyLightType;
  182 + }
  183 +
  184 + public Integer getDirectionType() {
  185 + return directionType;
  186 + }
  187 +
  188 + public void setDirectionType(Integer directionType) {
  189 + this.directionType = directionType;
  190 + }
  191 +}
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
@@ -63,7 +63,7 @@ public class SipLayer implements CommandLineRunner { @@ -63,7 +63,7 @@ public class SipLayer implements CommandLineRunner {
63 private void addListeningPoint(String monitorIp, int port){ 63 private void addListeningPoint(String monitorIp, int port){
64 SipStackImpl sipStack; 64 SipStackImpl sipStack;
65 try { 65 try {
66 - sipStack = (SipStackImpl)SipFactory.getInstance().createSipStack(DefaultProperties.getProperties(monitorIp, userSetting.getSipLog())); 66 + sipStack = (SipStackImpl)SipFactory.getInstance().createSipStack(DefaultProperties.getProperties("GB28181_SIP", userSetting.getSipLog()));
67 sipStack.setMessageParserFactory(new GbStringMsgParserFactory()); 67 sipStack.setMessageParserFactory(new GbStringMsgParserFactory());
68 } catch (PeerUnavailableException e) { 68 } catch (PeerUnavailableException e) {
69 logger.error("[SIP SERVER] SIP服务启动失败, 监听地址{}失败,请检查ip是否正确", monitorIp); 69 logger.error("[SIP SERVER] SIP服务启动失败, 监听地址{}失败,请检查ip是否正确", monitorIp);
src/main/java/com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java
@@ -12,10 +12,10 @@ import java.util.Properties; @@ -12,10 +12,10 @@ import java.util.Properties;
12 */ 12 */
13 public class DefaultProperties { 13 public class DefaultProperties {
14 14
15 - public static Properties getProperties(String ip, boolean sipLog) { 15 + public static Properties getProperties(String name, boolean sipLog) {
16 Properties properties = new Properties(); 16 Properties properties = new Properties();
17 - properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP");  
18 - properties.setProperty("javax.sip.IP_ADDRESS", ip); 17 + properties.setProperty("javax.sip.STACK_NAME", name);
  18 +// properties.setProperty("javax.sip.IP_ADDRESS", ip);
19 // 关闭自动会话 19 // 关闭自动会话
20 properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "off"); 20 properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "off");
21 /** 21 /**
src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java
@@ -344,7 +344,7 @@ public class XmlUtil { @@ -344,7 +344,7 @@ public class XmlUtil {
344 if (!ObjectUtils.isEmpty(civilCode) 344 if (!ObjectUtils.isEmpty(civilCode)
345 && civilCode.length() <= 8 345 && civilCode.length() <= 8
346 && NumberUtils.isParsable(civilCode) 346 && NumberUtils.isParsable(civilCode)
347 - && Integer.parseInt(civilCode)%2 == 0 347 + && civilCode.length()%2 == 0
348 ) { 348 ) {
349 deviceChannel.setCivilCode(civilCode); 349 deviceChannel.setCivilCode(civilCode);
350 } 350 }
src/main/java/com/genersoft/iot/vmp/media/zlm/SendRtpPortManager.java
@@ -3,12 +3,14 @@ package com.genersoft.iot.vmp.media.zlm; @@ -3,12 +3,14 @@ package com.genersoft.iot.vmp.media.zlm;
3 import com.genersoft.iot.vmp.common.VideoManagerConstants; 3 import com.genersoft.iot.vmp.common.VideoManagerConstants;
4 import com.genersoft.iot.vmp.conf.UserSetting; 4 import com.genersoft.iot.vmp.conf.UserSetting;
5 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; 5 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
6 -import com.genersoft.iot.vmp.media.zlm.dto.MediaSendRtpPortInfo; 6 +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
7 import com.genersoft.iot.vmp.utils.redis.RedisUtil; 7 import com.genersoft.iot.vmp.utils.redis.RedisUtil;
  8 +import org.apache.commons.lang3.math.NumberUtils;
8 import org.slf4j.Logger; 9 import org.slf4j.Logger;
9 import org.slf4j.LoggerFactory; 10 import org.slf4j.LoggerFactory;
10 import org.springframework.beans.factory.annotation.Autowired; 11 import org.springframework.beans.factory.annotation.Autowired;
11 import org.springframework.data.redis.core.RedisTemplate; 12 import org.springframework.data.redis.core.RedisTemplate;
  13 +import org.springframework.data.redis.support.atomic.RedisAtomicInteger;
12 import org.springframework.stereotype.Component; 14 import org.springframework.stereotype.Component;
13 15
14 import java.util.HashMap; 16 import java.util.HashMap;
@@ -26,23 +28,14 @@ public class SendRtpPortManager { @@ -26,23 +28,14 @@ public class SendRtpPortManager {
26 @Autowired 28 @Autowired
27 private RedisTemplate<Object, Object> redisTemplate; 29 private RedisTemplate<Object, Object> redisTemplate;
28 30
29 - private final String KEY = "VM_MEDIA_SEND_RTP_PORT_RANGE_"; 31 + private final String KEY = "VM_MEDIA_SEND_RTP_PORT_";
30 32
31 -  
32 - public void initServerPort(String mediaServerId, int startPort, int endPort){  
33 - String key = KEY + userSetting.getServerId() + "_" + mediaServerId;  
34 - MediaSendRtpPortInfo mediaSendRtpPortInfo = new MediaSendRtpPortInfo(startPort, endPort, mediaServerId);  
35 - redisTemplate.opsForValue().set(key, mediaSendRtpPortInfo);  
36 - }  
37 -  
38 - public int getNextPort(String mediaServerId) {  
39 - String sendIndexKey = KEY + userSetting.getServerId() + "_" + mediaServerId;  
40 - MediaSendRtpPortInfo mediaSendRtpPortInfo = (MediaSendRtpPortInfo)redisTemplate.opsForValue().get(sendIndexKey);  
41 - if (mediaSendRtpPortInfo == null) {  
42 - logger.warn("[发送端口管理] 获取{}的发送端口时未找到端口信息", mediaServerId);  
43 - return 0; 33 + public int getNextPort(MediaServerItem mediaServer) {
  34 + if (mediaServer == null) {
  35 + logger.warn("[发送端口管理] 参数错误,mediaServer为NULL");
  36 + return -1;
44 } 37 }
45 - 38 + String sendIndexKey = KEY + userSetting.getServerId() + "_" + mediaServer.getId();
46 String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX 39 String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX
47 + userSetting.getServerId() + "_*"; 40 + userSetting.getServerId() + "_*";
48 List<Object> queryResult = RedisUtil.scan(redisTemplate, key); 41 List<Object> queryResult = RedisUtil.scan(redisTemplate, key);
@@ -54,14 +47,39 @@ public class SendRtpPortManager { @@ -54,14 +47,39 @@ public class SendRtpPortManager {
54 sendRtpItemMap.put(sendRtpItem.getLocalPort(), sendRtpItem); 47 sendRtpItemMap.put(sendRtpItem.getLocalPort(), sendRtpItem);
55 } 48 }
56 } 49 }
  50 + String sendRtpPortRange = mediaServer.getSendRtpPortRange();
  51 + int startPort;
  52 + int endPort;
  53 + if (sendRtpPortRange == null) {
  54 + logger.warn("{}未设置发送端口默认值,自动使用40000-50000作为端口范围", mediaServer.getId());
  55 + String[] portArray = sendRtpPortRange.split(",");
  56 + if (portArray.length != 2 || !NumberUtils.isParsable(portArray[0]) || !NumberUtils.isParsable(portArray[1])) {
  57 + logger.warn("{}发送端口配置格式错误,自动使用40000-50000作为端口范围", mediaServer.getId());
  58 + startPort = 50000;
  59 + endPort = 60000;
  60 + }else {
57 61
58 - int port = getPort(mediaSendRtpPortInfo.getCurrent(),  
59 - mediaSendRtpPortInfo.getStart(),  
60 - mediaSendRtpPortInfo.getEnd(), checkPort -> sendRtpItemMap.get(checkPort) == null);  
61 -  
62 - mediaSendRtpPortInfo.setCurrent(port);  
63 - redisTemplate.opsForValue().set(sendIndexKey, mediaSendRtpPortInfo);  
64 - return port; 62 + if ( Integer.parseInt(portArray[1]) - Integer.parseInt(portArray[0]) < 1) {
  63 + logger.warn("{}发送端口配置错误,结束端口至少比开始端口大一,自动使用40000-50000作为端口范围", mediaServer.getId());
  64 + startPort = 50000;
  65 + endPort = 60000;
  66 + }else {
  67 + startPort = Integer.parseInt(portArray[0]);
  68 + endPort = Integer.parseInt(portArray[1]);
  69 + }
  70 + }
  71 + }else {
  72 + startPort = 50000;
  73 + endPort = 60000;
  74 + }
  75 + if (redisTemplate == null || redisTemplate.getConnectionFactory() == null) {
  76 + logger.warn("{}获取redis连接信息失败", mediaServer.getId());
  77 + return -1;
  78 + }
  79 + RedisAtomicInteger redisAtomicInteger = new RedisAtomicInteger(sendIndexKey , redisTemplate.getConnectionFactory());
  80 + return redisAtomicInteger.getAndUpdate((current)->{
  81 + return getPort(current, startPort, endPort, checkPort-> !sendRtpItemMap.containsKey(checkPort));
  82 + });
65 } 83 }
66 84
67 interface CheckPortCallback{ 85 interface CheckPortCallback{
@@ -69,22 +87,25 @@ public class SendRtpPortManager { @@ -69,22 +87,25 @@ public class SendRtpPortManager {
69 } 87 }
70 88
71 private int getPort(int current, int start, int end, CheckPortCallback checkPortCallback) { 89 private int getPort(int current, int start, int end, CheckPortCallback checkPortCallback) {
72 - int port;  
73 - if (current %2 != 0) {  
74 - port = current + 1;  
75 - }else {  
76 - port = current + 2;  
77 - }  
78 - if (port > end) {  
79 - if (start %2 != 0) {  
80 - port = start + 1; 90 + if (current <= 0) {
  91 + if (start%2 == 0) {
  92 + current = start;
81 }else { 93 }else {
82 - port = start; 94 + current = start + 1;
  95 + }
  96 + }else {
  97 + current += 2;
  98 + if (current > end) {
  99 + if (start%2 == 0) {
  100 + current = start;
  101 + }else {
  102 + current = start + 1;
  103 + }
83 } 104 }
84 } 105 }
85 - if (!checkPortCallback.check(port)) {  
86 - return getPort(port, start, end, checkPortCallback); 106 + if (!checkPortCallback.check(current)) {
  107 + return getPort(current + 2, start, end, checkPortCallback);
87 } 108 }
88 - return port; 109 + return current;
89 } 110 }
90 } 111 }
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerFactory.java
@@ -171,7 +171,7 @@ public class ZLMServerFactory { @@ -171,7 +171,7 @@ public class ZLMServerFactory {
171 // 默认为随机端口 171 // 默认为随机端口
172 int localPort = 0; 172 int localPort = 0;
173 if (userSetting.getGbSendStreamStrict()) { 173 if (userSetting.getGbSendStreamStrict()) {
174 - localPort = sendRtpPortManager.getNextPort(serverItem.getId()); 174 + localPort = sendRtpPortManager.getNextPort(serverItem);
175 if (localPort == 0) { 175 if (localPort == 0) {
176 return null; 176 return null;
177 } 177 }
@@ -207,7 +207,7 @@ public class ZLMServerFactory { @@ -207,7 +207,7 @@ public class ZLMServerFactory {
207 // 默认为随机端口 207 // 默认为随机端口
208 int localPort = 0; 208 int localPort = 0;
209 if (userSetting.getGbSendStreamStrict()) { 209 if (userSetting.getGbSendStreamStrict()) {
210 - localPort = sendRtpPortManager.getNextPort(serverItem.getId()); 210 + localPort = sendRtpPortManager.getNextPort(serverItem);
211 if (localPort == 0) { 211 if (localPort == 0) {
212 return null; 212 return null;
213 } 213 }
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaSendRtpPortInfo.java deleted 100644 → 0
1 -package com.genersoft.iot.vmp.media.zlm.dto;  
2 -  
3 -public class MediaSendRtpPortInfo {  
4 -  
5 - private int start;  
6 - private int end;  
7 - private String mediaServerId;  
8 -  
9 - private int current;  
10 -  
11 -  
12 - public MediaSendRtpPortInfo(int start, int end, String mediaServerId) {  
13 - this.start = start;  
14 - this.current = start;  
15 - this.end = end;  
16 - this.mediaServerId = mediaServerId;  
17 - }  
18 -  
19 - public int getStart() {  
20 - return start;  
21 - }  
22 -  
23 - public void setStart(int start) {  
24 - this.start = start;  
25 - }  
26 -  
27 - public int getEnd() {  
28 - return end;  
29 - }  
30 -  
31 - public void setEnd(int end) {  
32 - this.end = end;  
33 - }  
34 -  
35 - public String getMediaServerId() {  
36 - return mediaServerId;  
37 - }  
38 -  
39 - public void setMediaServerId(String mediaServerId) {  
40 - this.mediaServerId = mediaServerId;  
41 - }  
42 -  
43 - public int getCurrent() {  
44 - return current;  
45 - }  
46 -  
47 - public void setCurrent(int current) {  
48 - this.current = current;  
49 - }  
50 -}  
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
@@ -121,34 +121,6 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -121,34 +121,6 @@ public class MediaServerServiceImpl implements IMediaServerService {
121 if (ssrcFactory.hasMediaServerSSRC(mediaServerItem.getId())) { 121 if (ssrcFactory.hasMediaServerSSRC(mediaServerItem.getId())) {
122 ssrcFactory.initMediaServerSSRC(mediaServerItem.getId(), null); 122 ssrcFactory.initMediaServerSSRC(mediaServerItem.getId(), null);
123 } 123 }
124 - if (userSetting.getGbSendStreamStrict()) {  
125 - int startPort = 50000;  
126 - int endPort = 60000;  
127 - String sendRtpPortRange = mediaServerItem.getSendRtpPortRange();  
128 - if (sendRtpPortRange == null) {  
129 - logger.warn("[zlm] ] 未配置发流端口范围,默认使用50000到60000");  
130 - }else {  
131 - String[] sendRtpPortRangeArray = sendRtpPortRange.trim().split(",");  
132 - if (sendRtpPortRangeArray.length != 2) {  
133 - logger.warn("[zlm] ] 发流端口范围错误,默认使用50000到60000");  
134 - }else {  
135 - try {  
136 - startPort = Integer.parseInt(sendRtpPortRangeArray[0]);  
137 - endPort = Integer.parseInt(sendRtpPortRangeArray[1]);  
138 - if (endPort <= startPort) {  
139 - logger.warn("[zlm] ] 发流端口范围错误,结束端口应大于开始端口,使用默认端口");  
140 - startPort = 50000;  
141 - endPort = 60000;  
142 - }  
143 -  
144 - }catch (NumberFormatException e) {  
145 - logger.warn("[zlm] ] 发流端口范围错误,默认使用50000到60000");  
146 - }  
147 - }  
148 - }  
149 - logger.info("[[zlm] ] 配置发流端口范围,{}-{}", startPort, endPort);  
150 - sendRtpPortManager.initServerPort(mediaServerItem.getId(), startPort, endPort);  
151 - }  
152 // 查询redis是否存在此mediaServer 124 // 查询redis是否存在此mediaServer
153 String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(); 125 String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId();
154 Boolean hasKey = redisTemplate.hasKey(key); 126 Boolean hasKey = redisTemplate.hasKey(key);
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -440,7 +440,7 @@ public class PlayServiceImpl implements IPlayService { @@ -440,7 +440,7 @@ public class PlayServiceImpl implements IPlayService {
440 InviteErrorCode.SUCCESS.getCode(), 440 InviteErrorCode.SUCCESS.getCode(),
441 InviteErrorCode.SUCCESS.getMsg(), 441 InviteErrorCode.SUCCESS.getMsg(),
442 streamInfo); 442 streamInfo);
443 - logger.info("[点播成功] deviceId: {}, channelId:{}, 码流类型:{}", device.getDeviceId(), 443 + logger.info("[点播成功] deviceId: {}, channelId:{}, 码流类型:{}", device.getDeviceId(), channelId,
444 device.isSwitchPrimarySubStream() ? "辅码流" : "主码流"); 444 device.isSwitchPrimarySubStream() ? "辅码流" : "主码流");
445 snapOnPlay(mediaServerItemInuse, device.getDeviceId(), channelId, ssrcInfo.getStream()); 445 snapOnPlay(mediaServerItemInuse, device.getDeviceId(), channelId, ssrcInfo.getStream());
446 }, (event) -> { 446 }, (event) -> {
src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
@@ -155,25 +155,24 @@ public class StreamProxyServiceImpl implements IStreamProxyService { @@ -155,25 +155,24 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
155 return; 155 return;
156 } 156 }
157 157
158 - String talkKey = UUID.randomUUID().toString();  
159 - dynamicTask.startCron(talkKey, ()->{  
160 - StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(param.getApp(), param.getStream(), mediaInfo.getId(), false);  
161 - if (streamInfo != null) {  
162 - callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo);  
163 - }  
164 - }, 1000);  
165 - String delayTalkKey = UUID.randomUUID().toString();  
166 - dynamicTask.startDelay(delayTalkKey, ()->{  
167 - StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(param.getApp(), param.getStream(), mediaInfo.getId(), false);  
168 - if (streamInfo != null) {  
169 - callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo);  
170 - }else {  
171 - dynamicTask.stop(talkKey);  
172 - callback.run(ErrorCode.ERROR100.getCode(), "超时", null);  
173 - }  
174 - }, 5000);  
175 -  
176 if (param.isEnable()) { 158 if (param.isEnable()) {
  159 + String talkKey = UUID.randomUUID().toString();
  160 + dynamicTask.startCron(talkKey, ()->{
  161 + StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(param.getApp(), param.getStream(), mediaInfo.getId(), false);
  162 + if (streamInfo != null) {
  163 + callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo);
  164 + }
  165 + }, 1000);
  166 + String delayTalkKey = UUID.randomUUID().toString();
  167 + dynamicTask.startDelay(delayTalkKey, ()->{
  168 + StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(param.getApp(), param.getStream(), mediaInfo.getId(), false);
  169 + if (streamInfo != null) {
  170 + callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo);
  171 + }else {
  172 + dynamicTask.stop(talkKey);
  173 + callback.run(ErrorCode.ERROR100.getCode(), "超时", null);
  174 + }
  175 + }, 5000);
177 JSONObject jsonObject = addStreamProxyToZlm(param); 176 JSONObject jsonObject = addStreamProxyToZlm(param);
178 if (jsonObject != null && jsonObject.getInteger("code") == 0) { 177 if (jsonObject != null && jsonObject.getInteger("code") == 0) {
179 dynamicTask.stop(talkKey); 178 dynamicTask.stop(talkKey);
@@ -190,13 +189,16 @@ public class StreamProxyServiceImpl implements IStreamProxyService { @@ -190,13 +189,16 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
190 } 189 }
191 if (jsonObject == null){ 190 if (jsonObject == null){
192 callback.run(ErrorCode.ERROR100.getCode(), "记录已保存,启用失败", null); 191 callback.run(ErrorCode.ERROR100.getCode(), "记录已保存,启用失败", null);
193 - return;  
194 }else { 192 }else {
195 callback.run(ErrorCode.ERROR100.getCode(), jsonObject.getString("msg"), null); 193 callback.run(ErrorCode.ERROR100.getCode(), jsonObject.getString("msg"), null);
196 - return;  
197 } 194 }
198 } 195 }
199 } 196 }
  197 + else{
  198 + StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(
  199 + mediaInfo, param.getApp(), param.getStream(), null, null);
  200 + callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo);
  201 + }
200 } 202 }
201 203
202 private String getSchemaFromFFmpegCmd(String ffmpegCmd) { 204 private String getSchemaFromFFmpegCmd(String ffmpegCmd) {
src/main/java/com/genersoft/iot/vmp/vmanager/rtp/RtpController.java
@@ -139,8 +139,8 @@ public class RtpController { @@ -139,8 +139,8 @@ public class RtpController {
139 redisTemplate.opsForValue().set(receiveKey, otherRtpSendInfo); 139 redisTemplate.opsForValue().set(receiveKey, otherRtpSendInfo);
140 if (isSend != null && isSend) { 140 if (isSend != null && isSend) {
141 // 预创建发流信息 141 // 预创建发流信息
142 - int portForVideo = sendRtpPortManager.getNextPort(mediaServerItem.getId());  
143 - int portForAudio = sendRtpPortManager.getNextPort(mediaServerItem.getId()); 142 + int portForVideo = sendRtpPortManager.getNextPort(mediaServerItem);
  143 + int portForAudio = sendRtpPortManager.getNextPort(mediaServerItem);
144 144
145 otherRtpSendInfo.setSendLocalIp(mediaServerItem.getSdpIp()); 145 otherRtpSendInfo.setSendLocalIp(mediaServerItem.getSdpIp());
146 otherRtpSendInfo.setSendLocalPortForVideo(portForVideo); 146 otherRtpSendInfo.setSendLocalPortForVideo(portForVideo);
src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java
@@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.conf.SipConfig; @@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.conf.SipConfig;
8 import com.genersoft.iot.vmp.conf.UserSetting; 8 import com.genersoft.iot.vmp.conf.UserSetting;
9 import com.genersoft.iot.vmp.conf.VersionInfo; 9 import com.genersoft.iot.vmp.conf.VersionInfo;
10 import com.genersoft.iot.vmp.conf.exception.ControllerException; 10 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  11 +import com.genersoft.iot.vmp.media.zlm.SendRtpPortManager;
11 import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; 12 import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
12 import com.genersoft.iot.vmp.media.zlm.dto.IHookSubscribe; 13 import com.genersoft.iot.vmp.media.zlm.dto.IHookSubscribe;
13 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 14 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
@@ -72,6 +73,9 @@ public class ServerController { @@ -72,6 +73,9 @@ public class ServerController {
72 @Autowired 73 @Autowired
73 private IRedisCatchStorage redisCatchStorage; 74 private IRedisCatchStorage redisCatchStorage;
74 75
  76 + @Autowired
  77 + private SendRtpPortManager sendRtpPortManager;
  78 +
75 79
76 @GetMapping(value = "/media_server/list") 80 @GetMapping(value = "/media_server/list")
77 @ResponseBody 81 @ResponseBody
@@ -262,4 +266,12 @@ public class ServerController { @@ -262,4 +266,12 @@ public class ServerController {
262 266
263 return result; 267 return result;
264 } 268 }
  269 +
  270 + @PostMapping(value = "/test/getPort")
  271 + @ResponseBody
  272 + public int getPort() {
  273 + int result = sendRtpPortManager.getNextPort(mediaServerService.getDefaultMediaServer());
  274 + System.out.println(result);
  275 + return result;
  276 + }
265 } 277 }
src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java
@@ -52,14 +52,14 @@ public class ApiStreamController { @@ -52,14 +52,14 @@ public class ApiStreamController {
52 private IRedisCatchStorage redisCatchStorage; 52 private IRedisCatchStorage redisCatchStorage;
53 53
54 @Autowired 54 @Autowired
55 - private IInviteStreamService inviteStreamService;  
56 -  
57 - @Autowired  
58 private IDeviceService deviceService; 55 private IDeviceService deviceService;
59 56
60 @Autowired 57 @Autowired
61 private IPlayService playService; 58 private IPlayService playService;
62 59
  60 + @Autowired
  61 + private IInviteStreamService inviteStreamService;
  62 +
63 /** 63 /**
64 * 实时直播 - 开始直播 64 * 实时直播 - 开始直播
65 * @param serial 设备编号 65 * @param serial 设备编号
@@ -92,7 +92,7 @@ public class ApiStreamController { @@ -92,7 +92,7 @@ public class ApiStreamController {
92 result.put("error","device[ " + serial + " ]未找到"); 92 result.put("error","device[ " + serial + " ]未找到");
93 resultDeferredResult.setResult(result); 93 resultDeferredResult.setResult(result);
94 return resultDeferredResult; 94 return resultDeferredResult;
95 - }else if (!device.isOnLine()) { 95 + }else if (device.isOnLine()) {
96 JSONObject result = new JSONObject(); 96 JSONObject result = new JSONObject();
97 result.put("error","device[ " + code + " ]offline"); 97 result.put("error","device[ " + code + " ]offline");
98 resultDeferredResult.setResult(result); 98 resultDeferredResult.setResult(result);
@@ -133,11 +133,17 @@ public class ApiStreamController { @@ -133,11 +133,17 @@ public class ApiStreamController {
133 result.put("ChannelName", deviceChannel.getName()); 133 result.put("ChannelName", deviceChannel.getName());
134 result.put("ChannelCustomName", ""); 134 result.put("ChannelCustomName", "");
135 result.put("FLV", inviteInfo.getStreamInfo().getFlv().getUrl()); 135 result.put("FLV", inviteInfo.getStreamInfo().getFlv().getUrl());
  136 + result.put("HTTPS_FLV", inviteInfo.getStreamInfo().getHttps_flv().getUrl());
136 result.put("WS_FLV", inviteInfo.getStreamInfo().getWs_flv().getUrl()); 137 result.put("WS_FLV", inviteInfo.getStreamInfo().getWs_flv().getUrl());
  138 + result.put("WSS_FLV", inviteInfo.getStreamInfo().getWss_flv().getUrl());
137 result.put("RTMP", inviteInfo.getStreamInfo().getRtmp().getUrl()); 139 result.put("RTMP", inviteInfo.getStreamInfo().getRtmp().getUrl());
  140 + result.put("RTMPS", inviteInfo.getStreamInfo().getRtmps().getUrl());
138 result.put("HLS", inviteInfo.getStreamInfo().getHls().getUrl()); 141 result.put("HLS", inviteInfo.getStreamInfo().getHls().getUrl());
  142 + result.put("HTTPS_HLS", inviteInfo.getStreamInfo().getHttps_hls().getUrl());
139 result.put("RTSP", inviteInfo.getStreamInfo().getRtsp().getUrl()); 143 result.put("RTSP", inviteInfo.getStreamInfo().getRtsp().getUrl());
  144 + result.put("RTSPS", inviteInfo.getStreamInfo().getRtsps().getUrl());
140 result.put("WEBRTC", inviteInfo.getStreamInfo().getRtc().getUrl()); 145 result.put("WEBRTC", inviteInfo.getStreamInfo().getRtc().getUrl());
  146 + result.put("HTTPS_WEBRTC", inviteInfo.getStreamInfo().getRtcs().getUrl());
141 result.put("CDN", ""); 147 result.put("CDN", "");
142 result.put("SnapURL", ""); 148 result.put("SnapURL", "");
143 result.put("Transport", device.getTransport()); 149 result.put("Transport", device.getTransport());
src/main/resources/all-application.yml
@@ -145,8 +145,8 @@ media: @@ -145,8 +145,8 @@ media:
145 enable: true 145 enable: true
146 # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功 146 # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
147 port-range: 30000,30500 # 端口范围 147 port-range: 30000,30500 # 端口范围
148 - # [可选] 国标级联在此范围内选择端口发送媒体流  
149 - send-port-range: 30000,30500 # 端口范围 148 + # [可选] 国标级联在此范围内选择端口发送媒体流,请不要与收流端口范围重合
  149 + send-port-range: 50502,50506 # 端口范围
150 # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用 150 # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
151 record-assist-port: 0 151 record-assist-port: 0
152 152