Commit 3469271ec25c69e4528b085ba3be7d9d85ec519e

Authored by 64850858
1 parent 379830f7

优化集群方案, 每个zlm一套ssrc;

优化集群下的docker接入逻辑;
更正sql脚本;
支持重启不设置设备离线。重启SIP事务不丢失
Showing 56 changed files with 1312 additions and 1070 deletions
... ... @@ -46,6 +46,7 @@
46 46 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
47 47 <maven.build.timestamp.format>MMddHHmm</maven.build.timestamp.format>
48 48 <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
  49 + <jedis-version>3.1.0</jedis-version>
49 50  
50 51 <!-- 依赖版本 -->
51 52 <pagehelper.version>5.2.0</pagehelper.version>
... ... @@ -80,6 +81,12 @@
80 81 <artifactId>spring-boot-starter-security</artifactId>
81 82 </dependency>
82 83  
  84 + <dependency>
  85 + <groupId>redis.clients</groupId>
  86 + <artifactId>jedis</artifactId>
  87 + <version>${jedis-version}</version>
  88 + </dependency>
  89 +
83 90 <!-- druid数据库连接池 -->
84 91 <dependency>
85 92 <groupId>com.alibaba</groupId>
... ...
sql/mysql.sql
1 1 -- auto-generated definition
2   -create schema wvp collate utf8_bin;
  2 +
  3 +
  4 +CREATE DATABASE `wvp` /*!40100 DEFAULT CHARACTER SET utf8mb3 COLLATE utf8mb3_bin */;
  5 +
  6 +use wvp;
3 7  
4 8 create table device
5 9 (
6   - deviceId varchar(50) not null
  10 + deviceId varchar(50) not null
7 11 primary key,
8   - name varchar(255) null,
9   - manufacturer varchar(255) null,
10   - model varchar(255) null,
11   - firmware varchar(255) null,
12   - transport varchar(50) null,
13   - streamMode varchar(50) null,
14   - online varchar(50) null,
15   - registerTime varchar(50) null,
16   - keepaliveTime varchar(50) null,
17   - ip varchar(50) not null,
18   - createTime varchar(50) not null,
19   - updateTime varchar(50) not null,
20   - port int not null,
21   - expires int not null,
22   - hostAddress varchar(50) not null
  12 + name varchar(255) null,
  13 + manufacturer varchar(255) null,
  14 + model varchar(255) null,
  15 + firmware varchar(255) null,
  16 + transport varchar(50) null,
  17 + streamMode varchar(50) null,
  18 + online varchar(50) null,
  19 + registerTime varchar(50) null,
  20 + keepaliveTime varchar(50) null,
  21 + ip varchar(50) not null,
  22 + createTime varchar(50) not null,
  23 + updateTime varchar(50) not null,
  24 + port int not null,
  25 + expires int not null,
  26 + hostAddress varchar(50) not null
23 27 );
24 28  
25 29 create table device_channel
26 30 (
27   - channelId varchar(50) not null,
  31 + channelId varchar(50) not null,
28 32 name varchar(255) null,
29   - manufacture varchar(50) null,
30   - model varchar(50) null,
31   - owner varchar(50) null,
32   - civilCode varchar(50) null,
33   - block varchar(50) null,
34   - address varchar(50) null,
35   - parentId varchar(50) null,
  33 + manufacture varchar(50) null,
  34 + model varchar(50) null,
  35 + owner varchar(50) null,
  36 + civilCode varchar(50) null,
  37 + block varchar(50) null,
  38 + address varchar(50) null,
  39 + parentId varchar(50) null,
36 40 safetyWay int null,
37 41 registerWay int null,
38   - certNum varchar(50) null,
  42 + certNum varchar(50) null,
39 43 certifiable int null,
40 44 errCode int null,
41   - endTime varchar(50) null,
42   - secrecy varchar(50) null,
43   - ipAddress varchar(50) null,
  45 + endTime varchar(50) null,
  46 + secrecy varchar(50) null,
  47 + ipAddress varchar(50) null,
44 48 port int null,
45 49 password varchar(255) null,
46 50 PTZType int null,
47 51 status int null,
48 52 longitude double null,
49 53 latitude double null,
50   - streamId varchar(50) null,
51   - deviceId varchar(50) not null,
52   - parental varchar(50) null,
53   - hasAudio bit(1) null,
54   - createTime varchar(50) not null,
55   - updateTime varchar(50) not null,
  54 + streamId varchar(50) null,
  55 + deviceId varchar(50) not null,
  56 + parental varchar(50) null,
  57 + hasAudio bit null,
  58 + createTime varchar(50) not null,
  59 + updateTime varchar(50) not null,
56 60 primary key (channelId, deviceId)
57 61 );
58 62  
59 63 create table device_mobile_position
60 64 (
61   - deviceId varchar(50) not null,
  65 + deviceId varchar(50) not null,
62 66 deviceName varchar(255) null,
63   - time varchar(50) not null,
  67 + time varchar(50) not null,
64 68 longitude double not null,
65 69 latitude double not null,
66 70 altitude double null,
67 71 speed double null,
68 72 direction double null,
69   - reportSource varchar(50) null,
70   - geodeticSystem varchar(50) null,
71   - cnLng varchar(50) null,
72   - cnLat varchar(50) null,
  73 + reportSource varchar(50) null,
  74 + geodeticSystem varchar(50) null,
  75 + cnLng varchar(50) null,
  76 + cnLat varchar(50) null,
73 77 primary key (deviceId, time)
74 78 );
75 79  
76 80 create table gb_stream
77 81 (
78   - app varchar(255) not null,
79   - stream varchar(255) not null,
80   - gbId varchar(50) not null,
81   - name varchar(255) null,
82   - longitude double null,
83   - latitude double null,
84   - streamType varchar(50) null,
85   - status int null,
  82 + app varchar(255) not null,
  83 + stream varchar(255) not null,
  84 + gbId varchar(50) not null,
  85 + name varchar(255) null,
  86 + longitude double null,
  87 + latitude double null,
  88 + streamType varchar(50) null,
  89 + mediaServerId varchar(50) null,
  90 + status int null,
86 91 primary key (app, stream, gbId)
87 92 );
88 93  
  94 +create table media_server
  95 +(
  96 + id varchar(255) not null
  97 + primary key,
  98 + ip varchar(50) not null,
  99 + hookIp varchar(50) not null,
  100 + sdpIp varchar(50) not null,
  101 + streamIp varchar(50) not null,
  102 + httpPort int not null,
  103 + httpSSlPort int not null,
  104 + rtmpPort int not null,
  105 + rtmpSSlPort int not null,
  106 + rtpProxyPort int not null,
  107 + rtspPort int not null,
  108 + rtspSSLPort int not null,
  109 + autoConfig int not null,
  110 + secret varchar(50) not null,
  111 + streamNoneReaderDelayMS int not null,
  112 + rtpEnable int not null,
  113 + rtpPortRange varchar(50) not null,
  114 + recordAssistPort int not null,
  115 + defaultServer int not null,
  116 + createTime varchar(50) not null,
  117 + updateTime varchar(50) not null,
  118 + constraint media_server_i
  119 + unique (ip, httpPort)
  120 +);
  121 +
89 122 create table parent_platform
90 123 (
91   - id int auto_increment,
  124 + id int auto_increment,
92 125 enable int null,
93 126 name varchar(255) null,
94   - serverGBId varchar(50) not null,
95   - serverGBDomain varchar(50) null,
96   - serverIP varchar(50) null,
  127 + serverGBId varchar(50) not null,
  128 + serverGBDomain varchar(50) null,
  129 + serverIP varchar(50) null,
97 130 serverPort int null,
98   - deviceGBId varchar(50) not null,
99   - deviceIp varchar(50) null,
100   - devicePort varchar(50) null,
  131 + deviceGBId varchar(50) not null,
  132 + deviceIp varchar(50) null,
  133 + devicePort varchar(50) null,
101 134 username varchar(255) null,
102   - password varchar(50) null,
103   - expires varchar(50) null,
104   - keepTimeout varchar(50) null,
105   - transport varchar(50) null,
106   - characterSet varchar(50) null,
  135 + password varchar(50) null,
  136 + expires varchar(50) null,
  137 + keepTimeout varchar(50) null,
  138 + transport varchar(50) null,
  139 + characterSet varchar(50) null,
107 140 ptz int null,
108 141 rtcp int null,
109   - status bit(1) null,
  142 + status bit null,
110 143 primary key (id, serverGBId)
111 144 );
112 145  
... ... @@ -121,7 +154,7 @@ create table platform_gb_channel
121 154  
122 155 create table platform_gb_stream
123 156 (
124   - platformId varchar(50) not null,
  157 + platformId varchar(50) not null,
125 158 app varchar(255) not null,
126 159 stream varchar(255) not null,
127 160 primary key (platformId, app, stream)
... ... @@ -129,7 +162,7 @@ create table platform_gb_stream
129 162  
130 163 create table stream_proxy
131 164 (
132   - type varchar(50) not null,
  165 + type varchar(50) not null,
133 166 app varchar(255) not null,
134 167 stream varchar(255) not null,
135 168 url varchar(255) null,
... ... @@ -137,11 +170,12 @@ create table stream_proxy
137 170 dst_url varchar(255) null,
138 171 timeout_ms int null,
139 172 ffmpeg_cmd_key varchar(255) null,
140   - rtp_type varchar(50) null,
141   - mediaServerId varchar(50) null,
142   - enable_hls bit(1) null,
143   - enable_mp4 bit(1) null,
144   - enable bit(1) not null,
  173 + rtp_type varchar(50) null,
  174 + mediaServerId varchar(50) null,
  175 + enable_hls bit null,
  176 + enable_mp4 bit null,
  177 + enable bit not null,
  178 + createTime varchar(50) not null,
145 179 primary key (app, stream)
146 180 );
147 181  
... ... @@ -149,11 +183,12 @@ create table stream_push
149 183 (
150 184 app varchar(255) not null,
151 185 stream varchar(255) not null,
152   - totalReaderCount varchar(50) null,
  186 + totalReaderCount varchar(50) null,
153 187 originType int null,
154   - originTypeStr varchar(50) null,
  188 + originTypeStr varchar(50) null,
155 189 createStamp int null,
156 190 aliveSecond int null,
  191 + mediaServerId varchar(50) null,
157 192 primary key (app, stream)
158 193 );
159 194  
... ... @@ -164,31 +199,6 @@ create table user
164 199 username varchar(255) not null,
165 200 password varchar(255) not null,
166 201 roleId int not null,
167   - create_time varchar(50) not null
  202 + create_time varchar(50) not null
168 203 );
169 204  
170   -insert into user (username, password, roleId, create_time) values ('admin', '21232f297a57a5a743894a0e4a801fc3', '0', '2021-04-13 14:14:57');
171   -
172   -create table media_server (
173   - id varchar(255)
174   - primary key,
175   - ip varchar(50) NOT NULL,
176   - hookIp varchar(50) NOT NULL,
177   - sdpIp varchar(50) NOT NULL,
178   - streamIp varchar(50) NOT NULL,
179   - httpPort int NOT NULL,
180   - httpSSlPort int NOT NULL,
181   - rtmpPort int NOT NULL,
182   - rtmpSSlPort int NOT NULL,
183   - rtpProxyPort int NOT NULL,
184   - rtspPort int NOT NULL,
185   - rtspSSLPort int NOT NULL,
186   - autoConfig int NOT NULL,
187   - secret varchar(50) NOT NULL,
188   - streamNoneReaderDelayMS int NOT NULL,
189   - rtpEnable int NOT NULL,
190   - rtpPortRange varchar(50) NOT NULL,
191   - recordAssistPort int NOT NULL,
192   - createTime varchar(50) not null,
193   - updateTime varchar(50) not null
194   -);
195 205 \ No newline at end of file
... ...
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
... ... @@ -12,6 +12,8 @@ public class VideoManagerConstants {
12 12  
13 13 public static final String MEDIA_SERVER_PREFIX = "VMP_MEDIA_SERVER_";
14 14  
  15 + public static final String MEDIA_SERVERS_ONLINE_PREFIX = "VMP_MEDIA_ONLINE_SERVERS";
  16 +
15 17 public static final String MEDIA_STREAM_PREFIX = "VMP_MEDIA_STREAM";
16 18  
17 19 public static final String DEVICE_PREFIX = "VMP_DEVICE_";
... ... @@ -45,4 +47,8 @@ public class VideoManagerConstants {
45 47 public static final String EVENT_OUTLINE_UNREGISTER = "1";
46 48  
47 49 public static final String EVENT_OUTLINE_TIMEOUT = "2";
  50 +
  51 + public static final String MEDIA_SSRC_USED_PREFIX = "VMP_media_used_ssrc_";
  52 +
  53 + public static final String MEDIA_TRANSACTION_USED_PREFIX = "VMP_media_transaction_";
48 54 }
... ...
src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java
1 1 package com.genersoft.iot.vmp.conf;
2 2  
3   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
  3 +import com.genersoft.iot.vmp.gb28181.session.SsrcConfig;
4 4 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
5 5 import org.springframework.beans.factory.annotation.Value;
6 6 import org.springframework.context.annotation.Configuration;
7 7 import org.springframework.util.StringUtils;
8 8  
  9 +import java.text.SimpleDateFormat;
  10 +import java.util.Date;
  11 +
9 12 @Configuration("mediaConfig")
10   -public class MediaConfig implements IMediaServerItem {
  13 +public class MediaConfig{
11 14  
12 15 @Value("${media.id:}")
13 16 private String id;
... ... @@ -21,6 +24,9 @@ public class MediaConfig implements IMediaServerItem {
21 24 @Value("${sip.ip}")
22 25 private String sipIp;
23 26  
  27 + @Value("${sip.domain}")
  28 + private String sipDomain;
  29 +
24 30 @Value("${media.sdp-ip:${media.ip}}")
25 31 private String sdpIp;
26 32  
... ... @@ -66,31 +72,14 @@ public class MediaConfig implements IMediaServerItem {
66 72 @Value("${media.record-assist-port:0}")
67 73 private Integer recordAssistPort = 0;
68 74  
69   - private String updateTime;
70   -
71   - private String createTime;
72   -
73   - private boolean docker = false;
74   -
75   - private int count;
76   -
77   -
78 75 public String getId() {
79 76 return id;
80 77 }
81 78  
82   - public void setId(String id) {
83   - this.id = id;
84   - }
85   -
86 79 public String getIp() {
87 80 return ip;
88 81 }
89 82  
90   - public void setIp(String ip) {
91   - this.ip = ip;
92   - }
93   -
94 83 public String getHookIp() {
95 84 if (StringUtils.isEmpty(hookIp)){
96 85 return sipIp;
... ... @@ -100,78 +89,26 @@ public class MediaConfig implements IMediaServerItem {
100 89  
101 90 }
102 91  
103   - public void setHookIp(String hookIp) {
104   - this.hookIp = hookIp;
105   - }
106   -
107 92 public String getSipIp() {
108 93 return sipIp;
109 94 }
110 95  
111   - public void setSipIp(String sipIp) {
112   - this.sipIp = sipIp;
113   - }
114   -
115   - public void setSdpIp(String sdpIp) {
116   - this.sdpIp = sdpIp;
117   - }
118   -
119   - public void setStreamIp(String streamIp) {
120   - this.streamIp = streamIp;
121   - }
122   -
123 96 public int getHttpPort() {
124 97 return httpPort;
125 98 }
126 99  
127   - @Override
128   - public void setHttpPort(int httpPort) {
129   -
130   - }
131   -
132   - public void setHttpPort(Integer httpPort) {
133   - this.httpPort = httpPort;
134   - }
135   -
136 100 public int getHttpSSlPort() {
137 101 return httpSSlPort;
138 102 }
139 103  
140   - @Override
141   - public void setHttpSSlPort(int httpSSlPort) {
142   -
143   - }
144   -
145   - public void setHttpSSlPort(Integer httpSSlPort) {
146   - this.httpSSlPort = httpSSlPort;
147   - }
148   -
149 104 public int getRtmpPort() {
150 105 return rtmpPort;
151 106 }
152   -
153   - @Override
154   - public void setRtmpPort(int rtmpPort) {
155   -
156   - }
157   -
158   - public void setRtmpPort(Integer rtmpPort) {
159   - this.rtmpPort = rtmpPort;
160   - }
161   -
  107 +
162 108 public int getRtmpSSlPort() {
163 109 return rtmpSSlPort;
164 110 }
165 111  
166   - @Override
167   - public void setRtmpSSlPort(int rtmpSSlPort) {
168   -
169   - }
170   -
171   - public void setRtmpSSlPort(Integer rtmpSSlPort) {
172   - this.rtmpSSlPort = rtmpSSlPort;
173   - }
174   -
175 112 public int getRtpProxyPort() {
176 113 if (rtpProxyPort == null) {
177 114 return 0;
... ... @@ -181,104 +118,38 @@ public class MediaConfig implements IMediaServerItem {
181 118  
182 119 }
183 120  
184   - @Override
185   - public void setRtpProxyPort(int rtpProxyPort) {
186   -
187   - }
188   -
189   - public void setRtpProxyPort(Integer rtpProxyPort) {
190   - this.rtpProxyPort = rtpProxyPort;
191   - }
192   -
193 121 public int getRtspPort() {
194 122 return rtspPort;
195 123 }
196 124  
197   - @Override
198   - public void setRtspPort(int rtspPort) {
199   -
200   - }
201   -
202   - public void setRtspPort(Integer rtspPort) {
203   - this.rtspPort = rtspPort;
204   - }
205   -
206 125 public int getRtspSSLPort() {
207 126 return rtspSSLPort;
208 127 }
209 128  
210   - @Override
211   - public void setRtspSSLPort(int rtspSSLPort) {
212   -
213   - }
214   -
215   - public void setRtspSSLPort(Integer rtspSSLPort) {
216   - this.rtspSSLPort = rtspSSLPort;
217   - }
218   -
219 129 public boolean isAutoConfig() {
220 130 return autoConfig;
221 131 }
222 132  
223   - public void setAutoConfig(boolean autoConfig) {
224   - this.autoConfig = autoConfig;
225   - }
226   -
227 133 public String getSecret() {
228 134 return secret;
229 135 }
230 136  
231   - public void setSecret(String secret) {
232   - this.secret = secret;
233   - }
234   -
235 137 public String getStreamNoneReaderDelayMS() {
236 138 return streamNoneReaderDelayMS;
237 139 }
238 140  
239   - public void setStreamNoneReaderDelayMS(String streamNoneReaderDelayMS) {
240   - this.streamNoneReaderDelayMS = streamNoneReaderDelayMS;
241   - }
242   -
243 141 public boolean isRtpEnable() {
244 142 return rtpEnable;
245 143 }
246 144  
247   - public void setRtpEnable(boolean rtpEnable) {
248   - this.rtpEnable = rtpEnable;
249   - }
250   -
251 145 public String getRtpPortRange() {
252 146 return rtpPortRange;
253 147 }
254   -
255   - public void setRtpPortRange(String rtpPortRange) {
256   - this.rtpPortRange = rtpPortRange;
257   - }
258   -
  148 +
259 149 public int getRecordAssistPort() {
260 150 return recordAssistPort;
261 151 }
262 152  
263   - @Override
264   - public void setRecordAssistPort(int recordAssistPort) {
265   -
266   - }
267   -
268   - public void setRecordAssistPort(Integer recordAssistPort) {
269   - this.recordAssistPort = recordAssistPort;
270   - }
271   -
272   - @Override
273   - public boolean isDocker() {
274   - return docker;
275   - }
276   -
277   - @Override
278   - public void setDocker(boolean docker) {
279   - this.docker = docker;
280   - }
281   -
282 153 public String getSdpIp() {
283 154 if (StringUtils.isEmpty(sdpIp)){
284 155 return ip;
... ... @@ -295,13 +166,11 @@ public class MediaConfig implements IMediaServerItem {
295 166 }
296 167 }
297 168  
298   -
299   -
300 169 public MediaServerItem getMediaSerItem(){
301 170 MediaServerItem mediaServerItem = new MediaServerItem();
302 171 mediaServerItem.setId(id);
303 172 mediaServerItem.setIp(ip);
304   - mediaServerItem.setDocker(true);
  173 + mediaServerItem.setDefaultServer(true);
305 174 mediaServerItem.setHookIp(hookIp);
306 175 mediaServerItem.setSdpIp(sdpIp);
307 176 mediaServerItem.setStreamIp(streamIp);
... ... @@ -318,39 +187,12 @@ public class MediaConfig implements IMediaServerItem {
318 187 mediaServerItem.setRtpEnable(rtpEnable);
319 188 mediaServerItem.setRtpPortRange(rtpPortRange);
320 189 mediaServerItem.setRecordAssistPort(recordAssistPort);
321   - mediaServerItem.setCreateTime(createTime);
322   - mediaServerItem.setUpdateTime(updateTime);
323   - mediaServerItem.setCount(count);
324   - return mediaServerItem;
325   - }
326   -
327   - @Override
328   - public String getUpdateTime() {
329   - return updateTime;
330   - }
331 190  
332   - @Override
333   - public void setUpdateTime(String updateTime) {
334   - this.updateTime = updateTime;
335   - }
  191 + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  192 + mediaServerItem.setCreateTime(format.format(new Date(System.currentTimeMillis())));
  193 + mediaServerItem.setUpdateTime(format.format(new Date(System.currentTimeMillis())));
336 194  
337   - @Override
338   - public String getCreateTime() {
339   - return createTime;
340   - }
341   -
342   - @Override
343   - public void setCreateTime(String createTime) {
344   - this.createTime = createTime;
345   - }
346   -
347   - @Override
348   - public int getCount() {
349   - return count;
  195 + return mediaServerItem;
350 196 }
351 197  
352   - @Override
353   - public void setCount(int count) {
354   - this.count = count;
355   - }
356 198 }
... ...
src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java
1 1 package com.genersoft.iot.vmp.conf;
2 2  
3   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
  3 +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
4 4 import com.genersoft.iot.vmp.service.IMediaServerService;
5 5 import org.apache.catalina.connector.ClientAbortException;
6 6 import org.apache.http.HttpHost;
... ... @@ -49,7 +49,7 @@ public class ProxyServletConfig {
49 49 @Override
50 50 protected String rewriteQueryStringFromRequest(HttpServletRequest servletRequest, String queryString) {
51 51 String queryStr = super.rewriteQueryStringFromRequest(servletRequest, queryString);
52   - IMediaServerItem mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI());
  52 + MediaServerItem mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI());
53 53 if (mediaInfo != null) {
54 54 if (!StringUtils.isEmpty(queryStr)) {
55 55 queryStr += "&secret=" + mediaInfo.getSecret();
... ... @@ -88,7 +88,7 @@ public class ProxyServletConfig {
88 88 @Override
89 89 protected String getTargetUri(HttpServletRequest servletRequest) {
90 90 String requestURI = servletRequest.getRequestURI();
91   - IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
  91 + MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
92 92  
93 93 String uri = null;
94 94 if (mediaInfo != null) {
... ... @@ -106,7 +106,7 @@ public class ProxyServletConfig {
106 106 @Override
107 107 protected HttpHost getTargetHost(HttpServletRequest servletRequest) {
108 108 String requestURI = servletRequest.getRequestURI();
109   - IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
  109 + MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
110 110 HttpHost host;
111 111 if (mediaInfo != null) {
112 112 host = new HttpHost(mediaInfo.getIp(), mediaInfo.getHttpPort());
... ... @@ -120,7 +120,7 @@ public class ProxyServletConfig {
120 120 /**
121 121 * 根据uri获取流媒体信息
122 122 */
123   - IMediaServerItem getMediaInfoByUri(String uri){
  123 + MediaServerItem getMediaInfoByUri(String uri){
124 124 String[] split = uri.split("/");
125 125 String mediaServerId = split[2];
126 126 return mediaServerService.getOne(mediaServerId);
... ... @@ -132,7 +132,7 @@ public class ProxyServletConfig {
132 132 @Override
133 133 protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) {
134 134 String requestURI = servletRequest.getRequestURI();
135   - IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
  135 + MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
136 136 String url = super.rewriteUrlFromRequest(servletRequest);
137 137 if (mediaInfo == null) {
138 138 return url;
... ... @@ -186,7 +186,7 @@ public class ProxyServletConfig {
186 186 @Override
187 187 protected String getTargetUri(HttpServletRequest servletRequest) {
188 188 String requestURI = servletRequest.getRequestURI();
189   - IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
  189 + MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
190 190  
191 191 String uri = null;
192 192 if (mediaInfo != null) {
... ... @@ -204,7 +204,7 @@ public class ProxyServletConfig {
204 204 @Override
205 205 protected HttpHost getTargetHost(HttpServletRequest servletRequest) {
206 206 String requestURI = servletRequest.getRequestURI();
207   - IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
  207 + MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
208 208 HttpHost host;
209 209 if (mediaInfo != null) {
210 210 host = new HttpHost(mediaInfo.getIp(), mediaInfo.getRecordAssistPort());
... ... @@ -218,7 +218,7 @@ public class ProxyServletConfig {
218 218 /**
219 219 * 根据uri获取流媒体信息
220 220 */
221   - IMediaServerItem getMediaInfoByUri(String uri){
  221 + MediaServerItem getMediaInfoByUri(String uri){
222 222 String[] split = uri.split("/");
223 223 String mediaServerId = split[2];
224 224 return mediaServerService.getOne(mediaServerId);
... ... @@ -230,7 +230,7 @@ public class ProxyServletConfig {
230 230 @Override
231 231 protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) {
232 232 String requestURI = servletRequest.getRequestURI();
233   - IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
  233 + MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
234 234 String url = super.rewriteUrlFromRequest(servletRequest);
235 235 if (mediaInfo == null) {
236 236 return url;
... ...
src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java
1 1 package com.genersoft.iot.vmp.conf;
2 2  
  3 +import org.apache.commons.lang3.StringUtils;
  4 +import org.springframework.beans.factory.annotation.Value;
3 5 import org.springframework.cache.annotation.CachingConfigurerSupport;
4 6 import org.springframework.context.annotation.Bean;
5 7 import org.springframework.context.annotation.Configuration;
... ... @@ -10,6 +12,8 @@ import org.springframework.data.redis.serializer.StringRedisSerializer;
10 12  
11 13 import com.alibaba.fastjson.parser.ParserConfig;
12 14 import com.genersoft.iot.vmp.utils.redis.FastJsonRedisSerializer;
  15 +import redis.clients.jedis.JedisPool;
  16 +import redis.clients.jedis.JedisPoolConfig;
13 17  
14 18 /**
15 19 * @Description:Redis中间件配置类,使用spring-data-redis集成,自动从application.yml中加载redis配置
... ... @@ -20,6 +24,37 @@ import com.genersoft.iot.vmp.utils.redis.FastJsonRedisSerializer;
20 24 @Configuration
21 25 public class RedisConfig extends CachingConfigurerSupport {
22 26  
  27 + @Value("${spring.redis.host}")
  28 + private String host;
  29 + @Value("${spring.redis.port}")
  30 + private int port;
  31 + @Value("${spring.redis.database}")
  32 + private int database;
  33 + @Value("${spring.redis.password}")
  34 + private String password;
  35 + @Value("${spring.redis.timeout}")
  36 + private int timeout;
  37 + @Value("${spring.redis.poolMaxTotal:1000}")
  38 + private int poolMaxTotal;
  39 + @Value("${spring.redis.poolMaxIdle:500}")
  40 + private int poolMaxIdle;
  41 + @Value("${spring.redis.poolMaxWait:5}")
  42 + private int poolMaxWait;
  43 +
  44 + @Bean
  45 + public JedisPool jedisPool() {
  46 + if (StringUtils.isBlank(password)) {
  47 + password = null;
  48 + }
  49 + JedisPoolConfig poolConfig = new JedisPoolConfig();
  50 + poolConfig.setMaxIdle(poolMaxIdle);
  51 + poolConfig.setMaxTotal(poolMaxTotal);
  52 + // 秒转毫秒
  53 + poolConfig.setMaxWaitMillis(poolMaxWait * 1000L);
  54 + JedisPool jp = new JedisPool(poolConfig, host, port, timeout * 1000, password, database);
  55 + return jp;
  56 + }
  57 +
23 58 @Bean("redisTemplate")
24 59 public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
25 60 RedisTemplate<Object, Object> template = new RedisTemplate<>();
... ... @@ -34,7 +69,7 @@ public class RedisConfig extends CachingConfigurerSupport {
34 69 template.setHashKeySerializer(new StringRedisSerializer());
35 70 template.setConnectionFactory(redisConnectionFactory);
36 71 // 使用fastjson时需设置此项,否则会报异常not support type
37   - ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
  72 + ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
38 73 return template;
39 74 }
40 75  
... ...
src/main/java/com/genersoft/iot/vmp/conf/SipDeviceRunner.java deleted 100644 → 0
1   -package com.genersoft.iot.vmp.conf;
2   -
3   -import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
4   -import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
5   -import org.springframework.beans.factory.annotation.Autowired;
6   -import org.springframework.boot.CommandLineRunner;
7   -import org.springframework.core.annotation.Order;
8   -import org.springframework.stereotype.Component;
9   -
10   -
11   -/**
12   - * 系统启动时控制设备离线
13   - */
14   -@Component
15   -@Order(value=4)
16   -public class SipDeviceRunner implements CommandLineRunner {
17   -
18   - @Autowired
19   - private IVideoManagerStorager storager;
20   -
21   - @Autowired
22   - private IRedisCatchStorage redisCatchStorage;
23   -
24   - @Override
25   - public void run(String... args) throws Exception {
26   - // 设置所有设备离线
27   - storager.outlineForAll();
28   - // 设置所有设备离线
29   - redisCatchStorage.outlineForAll();
30   - }
31   -}
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
... ... @@ -12,6 +12,7 @@ import javax.sip.header.CallIdHeader;
12 12 import javax.sip.message.Response;
13 13  
14 14 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
  15 +import gov.nist.javax.sip.SipProviderImpl;
15 16 import org.slf4j.Logger;
16 17 import org.slf4j.LoggerFactory;
17 18 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -39,7 +40,7 @@ public class SipLayer implements SipListener {
39 40 @Autowired
40 41 private SipSubscribe sipSubscribe;
41 42  
42   - private SipStack sipStack;
  43 + private SipStackImpl sipStack;
43 44  
44 45 private SipFactory sipFactory;
45 46  
... ... @@ -52,7 +53,7 @@ public class SipLayer implements SipListener {
52 53 private ThreadPoolExecutor initSipServer() {
53 54  
54 55 int processThreadNum = Runtime.getRuntime().availableProcessors() * 10;
55   - LinkedBlockingQueue<Runnable> processQueue = new LinkedBlockingQueue<Runnable>(10000);
  56 + LinkedBlockingQueue<Runnable> processQueue = new LinkedBlockingQueue<>(10000);
56 57 processThreadPool = new ThreadPoolExecutor(processThreadNum,processThreadNum,
57 58 0L,TimeUnit.MILLISECONDS,processQueue,
58 59 new ThreadPoolExecutor.CallerRunsPolicy());
... ... @@ -88,17 +89,14 @@ public class SipLayer implements SipListener {
88 89  
89 90 @Bean("tcpSipProvider")
90 91 @DependsOn("sipStack")
91   - private SipProvider startTcpListener() {
  92 + private SipProviderImpl startTcpListener() {
92 93 ListeningPoint tcpListeningPoint = null;
93   - SipProvider tcpSipProvider = null;
  94 + SipProviderImpl tcpSipProvider = null;
94 95 try {
95 96 tcpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getSipPort(), "TCP");
96   - tcpSipProvider = sipStack.createSipProvider(tcpListeningPoint);
  97 + tcpSipProvider = (SipProviderImpl)sipStack.createSipProvider(tcpListeningPoint);
97 98 tcpSipProvider.addSipListener(this);
98 99 logger.info("Sip Server TCP 启动成功 port {" + sipConfig.getMonitorIp() + ":" + sipConfig.getSipPort() + "}");
99   -// } catch (TransportNotSupportedException | InvalidArgumentException | TooManyListenersException | ObjectInUseException e) {
100   -// logger.error(String.format("创建SIP服务失败: %s", e.getMessage()));
101   -// }
102 100 } catch (TransportNotSupportedException e) {
103 101 e.printStackTrace();
104 102 } catch (InvalidArgumentException e) {
... ... @@ -114,13 +112,14 @@ public class SipLayer implements SipListener {
114 112  
115 113 @Bean("udpSipProvider")
116 114 @DependsOn("sipStack")
117   - private SipProvider startUdpListener() {
  115 + private SipProviderImpl startUdpListener() {
118 116 ListeningPoint udpListeningPoint = null;
119   - SipProvider udpSipProvider = null;
  117 + SipProviderImpl udpSipProvider = null;
120 118 try {
121 119 udpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getSipPort(), "UDP");
122   - udpSipProvider = sipStack.createSipProvider(udpListeningPoint);
  120 + udpSipProvider = (SipProviderImpl)sipStack.createSipProvider(udpListeningPoint);
123 121 udpSipProvider.addSipListener(this);
  122 +// udpSipProvider.setAutomaticDialogSupportEnabled(false);
124 123 } catch (TransportNotSupportedException e) {
125 124 e.printStackTrace();
126 125 } catch (InvalidArgumentException e) {
... ... @@ -141,7 +140,7 @@ public class SipLayer implements SipListener {
141 140 */
142 141 @Override
143 142 public void processRequest(RequestEvent evt) {
144   -// logger.debug(evt.getRequest().toString());
  143 + logger.debug(evt.getRequest().toString());
145 144 // 由于jainsip是单线程程序,为提高性能并发处理
146 145 processThreadPool.execute(() -> {
147 146 if (processorFactory != null) {
... ... @@ -153,7 +152,7 @@ public class SipLayer implements SipListener {
153 152 @Override
154 153 public void processResponse(ResponseEvent evt) {
155 154 Response response = evt.getResponse();
156   -// logger.debug(evt.getResponse().toString());
  155 + logger.debug(evt.getResponse().toString());
157 156 int status = response.getStatusCode();
158 157 if (((status >= 200) && (status < 300)) || status == 401) { // Success!
159 158 ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt);
... ... @@ -163,6 +162,7 @@ public class SipLayer implements SipListener {
163 162 // TODO Auto-generated catch block
164 163 e.printStackTrace();
165 164 }
  165 +
166 166 if (evt.getResponse() != null && sipSubscribe.getOkSubscribesSize() > 0 ) {
167 167 CallIdHeader callIdHeader = (CallIdHeader)evt.getResponse().getHeader(CallIdHeader.NAME);
168 168 if (callIdHeader != null) {
... ... @@ -220,7 +220,6 @@ public class SipLayer implements SipListener {
220 220 @Override
221 221 public void processIOException(IOExceptionEvent exceptionEvent) {
222 222 // TODO Auto-generated method stub
223   -
224 223 }
225 224  
226 225 /**
... ... @@ -236,7 +235,6 @@ public class SipLayer implements SipListener {
236 235 @Override
237 236 public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
238 237 // TODO Auto-generated method stub
239   -
240 238 }
241 239  
242 240 /**
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.bean;
  2 +
  3 +import javax.sip.message.Request;
  4 +
  5 +public class SsrcTransaction {
  6 +
  7 + private String deviceId;
  8 + private String channelId;
  9 + private String ssrc;
  10 + private String streamId;
  11 + private byte[] transaction;
  12 + private byte[] dialog;
  13 + private String mediaServerId;
  14 +
  15 + public String getDeviceId() {
  16 + return deviceId;
  17 + }
  18 +
  19 + public void setDeviceId(String deviceId) {
  20 + this.deviceId = deviceId;
  21 + }
  22 +
  23 + public String getChannelId() {
  24 + return channelId;
  25 + }
  26 +
  27 + public void setChannelId(String channelId) {
  28 + this.channelId = channelId;
  29 + }
  30 +
  31 + public String getSsrc() {
  32 + return ssrc;
  33 + }
  34 +
  35 + public void setSsrc(String ssrc) {
  36 + this.ssrc = ssrc;
  37 + }
  38 +
  39 + public String getStreamId() {
  40 + return streamId;
  41 + }
  42 +
  43 + public void setStreamId(String streamId) {
  44 + this.streamId = streamId;
  45 + }
  46 +
  47 + public byte[] getTransaction() {
  48 + return transaction;
  49 + }
  50 +
  51 + public void setTransaction(byte[] transaction) {
  52 + this.transaction = transaction;
  53 + }
  54 +
  55 + public byte[] getDialog() {
  56 + return dialog;
  57 + }
  58 +
  59 + public void setDialog(byte[] dialog) {
  60 + this.dialog = dialog;
  61 + }
  62 +
  63 + public String getMediaServerId() {
  64 + return mediaServerId;
  65 + }
  66 +
  67 + public void setMediaServerId(String mediaServerId) {
  68 + this.mediaServerId = mediaServerId;
  69 + }
  70 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java
... ... @@ -6,7 +6,6 @@ import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
6 6 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
7 7 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
8 8 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
9   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
10 9 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
11 10 import com.genersoft.iot.vmp.service.IMediaServerService;
12 11 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
... ... @@ -77,7 +76,7 @@ public class PlatformNotRegisterEventLister implements ApplicationListener&lt;Platf
77 76 }
78 77 stream.append(sendRtpItem.getStreamId());
79 78 redisCatchStorage.deleteSendRTPServer(event.getPlatformGbID(), sendRtpItem.getChannelId());
80   - IMediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
  79 + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
81 80 Map<String, Object> param = new HashMap<>();
82 81 param.put("vhost", "__defaultVhost__");
83 82 param.put("app", app.toString());
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/session/SsrcUtil.java renamed to src/main/java/com/genersoft/iot/vmp/gb28181/session/SsrcConfig.java
1   -package com.genersoft.iot.vmp.gb28181.session;
2   -
3   -import java.util.ArrayList;
4   -import java.util.List;
5   -import java.util.Random;
6   -
7   -import com.genersoft.iot.vmp.conf.SipConfig;
8   -import com.genersoft.iot.vmp.utils.SpringBeanFactory;
9   -import org.slf4j.Logger;
10   -import org.slf4j.LoggerFactory;
11   -
12   -/**
13   - * @Description:SIP信令中的SSRC工具类。SSRC值由10位十进制整数组成的字符串,第一位为0代表实况,为1则代表回放;第二位至第六位由监控域ID的第4位到第8位组成;最后4位为不重复的4个整数
14   - * @author: swwheihei
15   - * @date: 2020年5月10日 上午11:57:57
16   - */
17   -public class SsrcUtil {
18   -
19   - private final static Logger logger = LoggerFactory.getLogger(SsrcUtil.class);
20   -
21   - private static String ssrcPrefix;
22   -
23   - private static List<String> isUsed;
24   -
25   - private static List<String> notUsed;
26   -
27   - private static void init() {
28   - SipConfig sipConfig = (SipConfig) SpringBeanFactory.getBean("sipConfig");
29   - ssrcPrefix = sipConfig.getSipDomain().substring(3, 8);
30   - isUsed = new ArrayList<String>();
31   - notUsed = new ArrayList<String>();
32   - for (int i = 1; i < 10000; i++) {
33   - if (i < 10) {
34   - notUsed.add("000" + i);
35   - } else if (i < 100) {
36   - notUsed.add("00" + i);
37   - } else if (i < 1000) {
38   - notUsed.add("0" + i);
39   - } else {
40   - notUsed.add(String.valueOf(i));
41   - }
42   - }
43   - }
44   -
45   - /**
46   - * 获取视频预览的SSRC值,第一位固定为0
47   - *
48   - */
49   - public static String getPlaySsrc() {
50   - return "0" + getSsrcPrefix() + getSN();
51   - }
52   -
53   - /**
54   - * 获取录像回放的SSRC值,第一位固定为1
55   - *
56   - */
57   - public static String getPlayBackSsrc() {
58   - return "1" + getSsrcPrefix() + getSN();
59   - }
60   -
61   - /**
62   - * 释放ssrc,主要用完的ssrc一定要释放,否则会耗尽
63   - *
64   - */
65   - public static void releaseSsrc(String ssrc) {
66   - if (ssrc == null) {
67   - logger.error("要释放ssrc为null");
68   - return;
69   - }
70   - String sn = ssrc.substring(6);
71   - isUsed.remove(sn);
72   - notUsed.add(sn);
73   - }
74   -
75   - /**
76   - * 获取后四位数SN,随机数
77   - *
78   - */
79   - private static String getSN() {
80   - String sn = null;
81   - int index = 0;
82   - if (notUsed.size() == 0) {
83   - throw new RuntimeException("ssrc已经用完");
84   - } else if (notUsed.size() == 1) {
85   - sn = notUsed.get(0);
86   - } else {
87   - index = new Random().nextInt(notUsed.size() - 1);
88   - sn = notUsed.get(index);
89   - }
90   - notUsed.remove(index);
91   - isUsed.add(sn);
92   - return sn;
93   - }
94   -
95   - private static String getSsrcPrefix() {
96   - if (ssrcPrefix == null) {
97   - init();
98   - }
99   - return ssrcPrefix;
100   - }
101   -}
  1 +package com.genersoft.iot.vmp.gb28181.session;
  2 +
  3 +import com.genersoft.iot.vmp.utils.ConfigConst;
  4 +
  5 +import java.util.ArrayList;
  6 +import java.util.List;
  7 +import java.util.Random;
  8 +import java.util.Set;
  9 +
  10 +public class SsrcConfig {
  11 +
  12 + /**
  13 + * zlm流媒体服务器Id
  14 + */
  15 + private String mediaServerId;
  16 +
  17 + private String ssrcPrefix;
  18 + /**
  19 + * zlm流媒体服务器已用会话句柄
  20 + */
  21 + private List<String> isUsed;
  22 + /**
  23 + * zlm流媒体服务器可用会话句柄
  24 + */
  25 + private List<String> notUsed;
  26 +
  27 + public SsrcConfig() {
  28 + }
  29 +
  30 + public SsrcConfig(String mediaServerId, Set<String> usedSet, String sipDomain) {
  31 + this.mediaServerId = mediaServerId;
  32 + this.isUsed = new ArrayList<>();
  33 + this.ssrcPrefix = sipDomain.substring(3, 8);
  34 + this.notUsed = new ArrayList<>();
  35 + for (int i = 1; i < ConfigConst.MAX_STRTEAM_COUNT; i++) {
  36 + String ssrc;
  37 + if (i < 10) {
  38 + ssrc = "000" + i;
  39 + } else if (i < 100) {
  40 + ssrc = "00" + i;
  41 + } else if (i < 1000) {
  42 + ssrc = "0" + i;
  43 + } else {
  44 + ssrc = String.valueOf(i);
  45 + }
  46 + if (null == usedSet || !usedSet.contains(ssrc)) {
  47 + this.notUsed.add(ssrc);
  48 + } else {
  49 + this.isUsed.add(ssrc);
  50 + }
  51 + }
  52 + }
  53 +
  54 +
  55 + /**
  56 + * 获取视频预览的SSRC值,第一位固定为0
  57 + * @return ssrc
  58 + */
  59 + public String getPlaySsrc() {
  60 + return "0" + getSsrcPrefix() + getSN();
  61 + }
  62 +
  63 + /**
  64 + * 获取录像回放的SSRC值,第一位固定为1
  65 + *
  66 + */
  67 + public String getPlayBackSsrc() {
  68 + return "1" + getSsrcPrefix() + getSN();
  69 + }
  70 +
  71 + /**
  72 + * 释放ssrc,主要用完的ssrc一定要释放,否则会耗尽
  73 + * @param ssrc 需要重置的ssrc
  74 + */
  75 + public void releaseSsrc(String ssrc) {
  76 + if (ssrc == null) {
  77 + return;
  78 + }
  79 + String sn = ssrc.substring(6);
  80 + try {
  81 + isUsed.remove(sn);
  82 + notUsed.add(sn);
  83 + }catch (NullPointerException e){
  84 + System.out.printf("11111");
  85 + }
  86 + }
  87 +
  88 + /**
  89 + * 获取后四位数SN,随机数
  90 + *
  91 + */
  92 + private String getSN() {
  93 + String sn = null;
  94 + int index = 0;
  95 + if (notUsed.size() == 0) {
  96 + throw new RuntimeException("ssrc已经用完");
  97 + } else if (notUsed.size() == 1) {
  98 + sn = notUsed.get(0);
  99 + } else {
  100 + index = new Random().nextInt(notUsed.size() - 1);
  101 + sn = notUsed.get(index);
  102 + }
  103 + notUsed.remove(index);
  104 + isUsed.add(sn);
  105 + return sn;
  106 + }
  107 +
  108 + public String getSsrcPrefix() {
  109 + return ssrcPrefix;
  110 + }
  111 +
  112 + public String getMediaServerId() {
  113 + return mediaServerId;
  114 + }
  115 +
  116 + public void setMediaServerId(String mediaServerId) {
  117 + this.mediaServerId = mediaServerId;
  118 + }
  119 +
  120 + public void setSsrcPrefix(String ssrcPrefix) {
  121 + this.ssrcPrefix = ssrcPrefix;
  122 + }
  123 +
  124 + public List<String> getIsUsed() {
  125 + return isUsed;
  126 + }
  127 +
  128 + public void setIsUsed(List<String> isUsed) {
  129 + this.isUsed = isUsed;
  130 + }
  131 +
  132 + public List<String> getNotUsed() {
  133 + return notUsed;
  134 + }
  135 +
  136 + public void setNotUsed(List<String> notUsed) {
  137 + this.notUsed = notUsed;
  138 + }
  139 +
  140 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java
1 1 package com.genersoft.iot.vmp.gb28181.session;
2 2  
  3 +import java.util.ArrayList;
  4 +import java.util.List;
  5 +import java.util.Map;
3 6 import java.util.concurrent.ConcurrentHashMap;
4 7  
5 8 import javax.sip.ClientTransaction;
  9 +import javax.sip.Dialog;
  10 +import javax.sip.message.Request;
6 11  
  12 +import com.genersoft.iot.vmp.common.VideoManagerConstants;
  13 +import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
  14 +import com.genersoft.iot.vmp.service.IMediaServerService;
  15 +import com.genersoft.iot.vmp.utils.SerializeUtils;
  16 +import com.genersoft.iot.vmp.utils.redis.JedisUtil;
  17 +import com.genersoft.iot.vmp.utils.redis.RedisUtil;
  18 +import gov.nist.javax.sip.stack.SIPDialog;
  19 +import org.springframework.beans.factory.annotation.Autowired;
  20 +import org.springframework.data.redis.core.RedisTemplate;
7 21 import org.springframework.stereotype.Component;
8 22  
9 23 /**
... ... @@ -14,50 +28,85 @@ import org.springframework.stereotype.Component;
14 28 @Component
15 29 public class VideoStreamSessionManager {
16 30  
17   - private ConcurrentHashMap<String, ClientTransaction> sessionMap = new ConcurrentHashMap<>();
18   - private ConcurrentHashMap<String, String> ssrcMap = new ConcurrentHashMap<>();
19   - private ConcurrentHashMap<String, String> streamIdMap = new ConcurrentHashMap<>();
  31 + @Autowired
  32 + private RedisUtil redisUtil;
20 33  
21   - public String createPlaySsrc(){
22   - return SsrcUtil.getPlaySsrc();
23   - }
24   -
25   - public String createPlayBackSsrc(){
26   - return SsrcUtil.getPlayBackSsrc();
  34 + public void put(String deviceId, String channelId ,String ssrc, String streamId, String mediaServerId, ClientTransaction transaction){
  35 + SsrcTransaction ssrcTransaction = new SsrcTransaction();
  36 + ssrcTransaction.setDeviceId(deviceId);
  37 + ssrcTransaction.setChannelId(channelId);
  38 + ssrcTransaction.setStreamId(streamId);
  39 + byte[] transactionByteArray = SerializeUtils.serialize(transaction);
  40 + ssrcTransaction.setTransaction(transactionByteArray);
  41 + ssrcTransaction.setSsrc(ssrc);
  42 + ssrcTransaction.setMediaServerId(mediaServerId);
  43 +
  44 + redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + deviceId + "_" + channelId, ssrcTransaction);
27 45 }
28   -
29   - public void put(String deviceId, String channelId ,String ssrc, String streamId, ClientTransaction transaction){
30   - sessionMap.put(deviceId + "_" + channelId, transaction);
31   - ssrcMap.put(deviceId + "_" + channelId, ssrc);
32   - streamIdMap.put(deviceId + "_" + channelId, streamId);
  46 +
  47 + public void put(String deviceId, String channelId , Dialog dialog){
  48 + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
  49 + if (ssrcTransaction != null) {
  50 + byte[] dialogByteArray = SerializeUtils.serialize(dialog);
  51 + ssrcTransaction.setDialog(dialogByteArray);
  52 + }
  53 + redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + deviceId + "_" + channelId, ssrcTransaction);
33 54 }
  55 +
34 56  
35 57 public ClientTransaction getTransaction(String deviceId, String channelId){
36   - return sessionMap.get(deviceId + "_" + channelId);
  58 + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
  59 + if (ssrcTransaction == null) return null;
  60 + byte[] transactionByteArray = ssrcTransaction.getTransaction();
  61 + ClientTransaction clientTransaction = (ClientTransaction)SerializeUtils.deSerialize(transactionByteArray);
  62 + return clientTransaction;
37 63 }
38 64  
39   - public String getStreamId(String deviceId, String channelId){
40   - return streamIdMap.get(deviceId + "_" + channelId);
  65 + public SIPDialog getDialog(String deviceId, String channelId){
  66 + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
  67 + if (ssrcTransaction == null) return null;
  68 + byte[] dialogByteArray = ssrcTransaction.getDialog();
  69 + if (dialogByteArray == null) return null;
  70 + SIPDialog dialog = (SIPDialog)SerializeUtils.deSerialize(dialogByteArray);
  71 + return dialog;
41 72 }
42   -
43   - public void remove(String deviceId, String channelId) {
44   - sessionMap.remove(deviceId + "_" + channelId);
45   - if (ssrcMap.get(deviceId + "_" + channelId) != null) {
46   - SsrcUtil.releaseSsrc(ssrcMap.get(deviceId + "_" + channelId));
47   - }
48   - ssrcMap.remove(deviceId + "_" + channelId);
49   - streamIdMap.remove(deviceId + "_" + channelId);
  73 +
  74 + public SsrcTransaction getSsrcTransaction(String deviceId, String channelId){
  75 + SsrcTransaction ssrcTransaction = (SsrcTransaction)redisUtil.get(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + deviceId + "_" + channelId);
  76 + return ssrcTransaction;
50 77 }
51 78  
52   - public ConcurrentHashMap<String, ClientTransaction> getSessionMap() {
53   - return sessionMap;
  79 + public String getStreamId(String deviceId, String channelId){
  80 + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
  81 + if (ssrcTransaction == null) return null;
  82 + return ssrcTransaction.getStreamId();
  83 + }
  84 + public String getMediaServerId(String deviceId, String channelId){
  85 + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
  86 + if (ssrcTransaction == null) return null;
  87 + return ssrcTransaction.getMediaServerId();
54 88 }
55 89  
56   - public ConcurrentHashMap<String, String> getSsrcMap() {
57   - return ssrcMap;
  90 + public String getSSRC(String deviceId, String channelId){
  91 + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
  92 + if (ssrcTransaction == null) return null;
  93 + return ssrcTransaction.getSsrc();
  94 + }
  95 +
  96 + public void remove(String deviceId, String channelId) {
  97 + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
  98 + if (ssrcTransaction == null) return;
  99 + redisUtil.del(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + deviceId + "_" + channelId);
58 100 }
59 101  
60   - public ConcurrentHashMap<String, String> getStreamIdMap() {
61   - return streamIdMap;
  102 + public List<SsrcTransaction> getAllSsrc() {
  103 + List<Object> ssrcTransactionKeys = redisUtil.scan(String.format("%s_*_*", VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX));
  104 + List<SsrcTransaction> result= new ArrayList<>();
  105 + for (int i = 0; i < ssrcTransactionKeys.size(); i++) {
  106 + String key = (String)ssrcTransactionKeys.get(i);
  107 + SsrcTransaction ssrcTransaction = (SsrcTransaction)redisUtil.get(key);
  108 + result.add(ssrcTransaction);
  109 + }
  110 + return result;
62 111 }
63 112 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java
... ... @@ -7,6 +7,7 @@ import javax.sip.header.CSeqHeader;
7 7 import javax.sip.message.Request;
8 8 import javax.sip.message.Response;
9 9  
  10 +import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
10 11 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
11 12 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
12 13 import com.genersoft.iot.vmp.service.IMediaServerService;
... ... @@ -108,7 +109,6 @@ public class SIPProcessorFactory {
108 109 @Autowired
109 110 private IMediaServerService mediaServerService;
110 111  
111   -
112 112 // 注:这里使用注解会导致循环依赖注入,暂用springBean
113 113 private SipProvider tcpSipProvider;
114 114  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
... ... @@ -3,8 +3,8 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd;
3 3 import com.genersoft.iot.vmp.gb28181.bean.Device;
4 4 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
5 5 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
6   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
7 6 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
  7 +import com.genersoft.iot.vmp.service.bean.SSRCInfo;
8 8  
9 9 /**
10 10 * @Description:设备能力接口,用于定义设备的控制、查询能力
... ... @@ -92,7 +92,7 @@ public interface ISIPCommander {
92 92 * @param device 视频设备
93 93 * @param channelId 预览通道
94 94 */
95   - void playStreamCmd(IMediaServerItem mediaServerItem, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
  95 + void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
96 96  
97 97 /**
98 98 * 请求回放视频流
... ... @@ -102,7 +102,7 @@ public interface ISIPCommander {
102 102 * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
103 103 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
104 104 */
105   - void playbackStreamCmd(IMediaServerItem mediaServerItem,Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
  105 + void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInf, Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
106 106  
107 107 /**
108 108 * 请求历史媒体下载
... ... @@ -113,12 +113,10 @@ public interface ISIPCommander {
113 113 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
114 114 * @param downloadSpeed 下载倍速参数
115 115 */
116   - void downloadStreamCmd(IMediaServerItem mediaServerItem,Device device, String channelId, String startTime, String endTime, String downloadSpeed, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
  116 + void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, String startTime, String endTime, String downloadSpeed, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
117 117  
118 118 /**
119 119 * 视频流停止
120   - *
121   - * @param ssrc ssrc
122 120 */
123 121 void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent);
124 122 void streamByeCmd(String deviceId, String channelId);
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
1 1 package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
2 2  
  3 +import java.lang.reflect.Field;
3 4 import java.text.ParseException;
  5 +import java.util.HashSet;
4 6  
5 7 import javax.sip.*;
6 8 import javax.sip.address.SipURI;
... ... @@ -8,18 +10,21 @@ import javax.sip.header.CallIdHeader;
8 10 import javax.sip.header.ViaHeader;
9 11 import javax.sip.message.Request;
10 12  
11   -import com.alibaba.fastjson.JSONArray;
12 13 import com.alibaba.fastjson.JSONObject;
13   -import com.genersoft.iot.vmp.common.StreamInfo;
14   -import com.genersoft.iot.vmp.conf.MediaConfig;
15 14 import com.genersoft.iot.vmp.conf.UserSetup;
  15 +import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
16 16 import com.genersoft.iot.vmp.media.zlm.*;
17 17 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
18   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
19 18 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
  19 +import com.genersoft.iot.vmp.service.IMediaServerService;
  20 +import com.genersoft.iot.vmp.service.bean.SSRCInfo;
20 21 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
21 22 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  23 +import gov.nist.javax.sip.SipProviderImpl;
  24 +import gov.nist.javax.sip.SipStackImpl;
22 25 import gov.nist.javax.sip.message.SIPRequest;
  26 +import gov.nist.javax.sip.stack.SIPDialog;
  27 +import gov.nist.javax.sip.stack.SIPTransaction;
23 28 import org.slf4j.Logger;
24 29 import org.slf4j.LoggerFactory;
25 30 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -35,7 +40,6 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
35 40 import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
36 41 import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
37 42 import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
38   -import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
39 43 import org.springframework.util.StringUtils;
40 44  
41 45 /**
... ... @@ -55,12 +59,12 @@ public class SIPCommander implements ISIPCommander {
55 59 @Lazy
56 60 @Autowired
57 61 @Qualifier(value="tcpSipProvider")
58   - private SipProvider tcpSipProvider;
  62 + private SipProviderImpl tcpSipProvider;
59 63  
60 64 @Lazy
61 65 @Autowired
62 66 @Qualifier(value="udpSipProvider")
63   - private SipProvider udpSipProvider;
  67 + private SipProviderImpl udpSipProvider;
64 68  
65 69 @Autowired
66 70 private SIPRequestHeaderProvider headerProvider;
... ... @@ -75,9 +79,6 @@ public class SIPCommander implements ISIPCommander {
75 79 private IRedisCatchStorage redisCatchStorage;
76 80  
77 81 @Autowired
78   - private ZLMRTPServerFactory zlmrtpServerFactory;
79   -
80   - @Autowired
81 82 private UserSetup userSetup;
82 83  
83 84 @Autowired
... ... @@ -86,6 +87,11 @@ public class SIPCommander implements ISIPCommander {
86 87 @Autowired
87 88 private SipSubscribe sipSubscribe;
88 89  
  90 + @Autowired
  91 + private IMediaServerService mediaServerService;
  92 +
  93 + private SIPDialog dialog;
  94 +
89 95 public SipConfig getSipConfig() {
90 96 return sipConfig;
91 97 }
... ... @@ -334,26 +340,13 @@ public class SIPCommander implements ISIPCommander {
334 340 * @param errorEvent sip错误订阅
335 341 */
336 342 @Override
337   - public void playStreamCmd(IMediaServerItem mediaServerItem, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent) {
338   - String streamId = null;
  343 + public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent) {
  344 + String streamId = ssrcInfo.getStreamId();
339 345 try {
340 346 if (device == null) return;
341 347 String streamMode = device.getStreamMode().toUpperCase();
342 348  
343   - String ssrc = streamSession.createPlaySsrc();
344   - if (mediaServerItem.isRtpEnable()) {
345   - streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
346   - }else {
347   - streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
348   - }
349   - Integer mediaPort = null;
350   - // 使用动态udp端口
351   - if (mediaServerItem.isRtpEnable()) {
352   - mediaPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId);
353   - }else {
354   - mediaPort = mediaServerItem.getRtpProxyPort();
355   - }
356   - logger.info("{} 分配的ZLM为: {} [{}:{}]", streamId, mediaServerItem.getId(), mediaServerItem.getIp(), mediaPort);
  349 + logger.info("{} 分配的ZLM为: {} [{}:{}]", streamId, mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
357 350 // 添加订阅
358 351 JSONObject subscribeKey = new JSONObject();
359 352 subscribeKey.put("app", "rtp");
... ... @@ -361,7 +354,7 @@ public class SIPCommander implements ISIPCommander {
361 354 subscribeKey.put("regist", true);
362 355 subscribeKey.put("mediaServerId", mediaServerItem.getId());
363 356 subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
364   - (IMediaServerItem mediaServerItemInUse, JSONObject json)->{
  357 + (MediaServerItem mediaServerItemInUse, JSONObject json)->{
365 358 if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
366 359 event.response(mediaServerItemInUse, json);
367 360 subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
... ... @@ -369,7 +362,6 @@ public class SIPCommander implements ISIPCommander {
369 362 //
370 363 StringBuffer content = new StringBuffer(200);
371 364 content.append("v=0\r\n");
372   -// content.append("o=" + sipConfig.getSipId() + " 0 0 IN IP4 "+mediaInfo.getWanIp()+"\r\n");
373 365 content.append("o="+"00000"+" 0 0 IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");
374 366 content.append("s=Play\r\n");
375 367 content.append("c=IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");
... ... @@ -377,11 +369,11 @@ public class SIPCommander implements ISIPCommander {
377 369  
378 370 if (userSetup.isSeniorSdp()) {
379 371 if("TCP-PASSIVE".equals(streamMode)) {
380   - content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
  372 + content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
381 373 }else if ("TCP-ACTIVE".equals(streamMode)) {
382   - content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
  374 + content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
383 375 }else if("UDP".equals(streamMode)) {
384   - content.append("m=video "+ mediaPort +" RTP/AVP 96 126 125 99 34 98 97\r\n");
  376 + content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 126 125 99 34 98 97\r\n");
385 377 }
386 378 content.append("a=recvonly\r\n");
387 379 content.append("a=rtpmap:96 PS/90000\r\n");
... ... @@ -402,11 +394,11 @@ public class SIPCommander implements ISIPCommander {
402 394 }
403 395 }else {
404 396 if("TCP-PASSIVE".equals(streamMode)) {
405   - content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 98 97\r\n");
  397 + content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n");
406 398 }else if ("TCP-ACTIVE".equals(streamMode)) {
407   - content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 98 97\r\n");
  399 + content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n");
408 400 }else if("UDP".equals(streamMode)) {
409   - content.append("m=video "+ mediaPort +" RTP/AVP 96 98 97\r\n");
  401 + content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 98 97\r\n");
410 402 }
411 403 content.append("a=recvonly\r\n");
412 404 content.append("a=rtpmap:96 PS/90000\r\n");
... ... @@ -421,20 +413,25 @@ public class SIPCommander implements ISIPCommander {
421 413 }
422 414 }
423 415  
424   - content.append("y="+ssrc+"\r\n");//ssrc
  416 + content.append("y="+ssrcInfo.getSsrc()+"\r\n");//ssrc
425 417  
426 418 String tm = Long.toString(System.currentTimeMillis());
427 419  
428 420 CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
429 421 : udpSipProvider.getNewCallId();
430 422  
431   - Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, "FromInvt" + tm, null, ssrc, callIdHeader);
  423 + Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, "FromInvt" + tm, null, ssrcInfo.getSsrc(), callIdHeader);
432 424  
433   - ClientTransaction transaction = transmitRequest(device, request, (e -> {
  425 + String finalStreamId = streamId;
  426 + transmitRequest(device, request, (e -> {
434 427 streamSession.remove(device.getDeviceId(), channelId);
  428 + mediaServerService.releaseSsrc(mediaServerItem, ssrcInfo.getSsrc());
435 429 errorEvent.response(e);
436   - }));
437   - streamSession.put(device.getDeviceId(), channelId ,ssrc,streamId, transaction);
  430 + }), e ->{
  431 + streamSession.put(device.getDeviceId(), channelId ,ssrcInfo.getSsrc(), finalStreamId, mediaServerItem.getId(),e.getClientTransaction());
  432 + streamSession.put(device.getDeviceId(), channelId , e.getDialog());
  433 + });
  434 +
438 435  
439 436 } catch ( SipException | ParseException | InvalidArgumentException e) {
440 437 e.printStackTrace();
... ... @@ -450,30 +447,21 @@ public class SIPCommander implements ISIPCommander {
450 447 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
451 448 */
452 449 @Override
453   - public void playbackStreamCmd(IMediaServerItem mediaServerItem,Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event
  450 + public void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event
454 451 , SipSubscribe.Event errorEvent) {
455 452 try {
456   - String ssrc = streamSession.createPlayBackSsrc();
457   - String streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
458 453  
459   - Integer mediaPort = null;
460   - // 使用动态udp端口
461   - if (mediaServerItem.isRtpEnable()) {
462   - mediaPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId);
463   - }else {
464   - mediaPort = mediaServerItem.getRtpProxyPort();
465   - }
466   - logger.info("{} 分配的ZLM为: {} [{}:{}]", streamId, mediaServerItem.getId(), mediaServerItem.getIp(), mediaPort);
  454 + logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStreamId(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
467 455  
468 456 // 添加订阅
469 457 JSONObject subscribeKey = new JSONObject();
470 458 subscribeKey.put("app", "rtp");
471   - subscribeKey.put("stream", streamId);
  459 + subscribeKey.put("stream", ssrcInfo.getStreamId());
472 460 subscribeKey.put("regist", true);
473 461 subscribeKey.put("mediaServerId", mediaServerItem.getId());
474 462 logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString());
475 463 subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
476   - (IMediaServerItem mediaServerItemInUse, JSONObject json)->{
  464 + (MediaServerItem mediaServerItemInUse, JSONObject json)->{
477 465 if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
478 466 event.response(mediaServerItemInUse, json);
479 467 subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
... ... @@ -494,11 +482,11 @@ public class SIPCommander implements ISIPCommander {
494 482  
495 483 if (userSetup.isSeniorSdp()) {
496 484 if("TCP-PASSIVE".equals(streamMode)) {
497   - content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
  485 + content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
498 486 }else if ("TCP-ACTIVE".equals(streamMode)) {
499   - content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
  487 + content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
500 488 }else if("UDP".equals(streamMode)) {
501   - content.append("m=video "+ mediaPort +" RTP/AVP 96 126 125 99 34 98 97\r\n");
  489 + content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 126 125 99 34 98 97\r\n");
502 490 }
503 491 content.append("a=recvonly\r\n");
504 492 content.append("a=rtpmap:96 PS/90000\r\n");
... ... @@ -519,11 +507,11 @@ public class SIPCommander implements ISIPCommander {
519 507 }
520 508 }else {
521 509 if("TCP-PASSIVE".equals(streamMode)) {
522   - content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 98 97\r\n");
  510 + content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n");
523 511 }else if ("TCP-ACTIVE".equals(streamMode)) {
524   - content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 98 97\r\n");
  512 + content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n");
525 513 }else if("UDP".equals(streamMode)) {
526   - content.append("m=video "+ mediaPort +" RTP/AVP 96 98 97\r\n");
  514 + content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 98 97\r\n");
527 515 }
528 516 content.append("a=recvonly\r\n");
529 517 content.append("a=rtpmap:96 PS/90000\r\n");
... ... @@ -538,7 +526,7 @@ public class SIPCommander implements ISIPCommander {
538 526 }
539 527 }
540 528  
541   - content.append("y="+ssrc+"\r\n");//ssrc
  529 + content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
542 530  
543 531 String tm = Long.toString(System.currentTimeMillis());
544 532  
... ... @@ -547,9 +535,11 @@ public class SIPCommander implements ISIPCommander {
547 535  
548 536 Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader);
549 537  
550   - ClientTransaction transaction = transmitRequest(device, request, errorEvent);
551   - streamSession.put(device.getDeviceId(), channelId, ssrc, streamId, transaction);
552   -
  538 + transmitRequest(device, request, errorEvent, okEvent -> {
  539 + Dialog dialog = okEvent.getClientTransaction().getDialog();
  540 + streamSession.put(device.getDeviceId(), channelId, ssrcInfo.getSsrc(), ssrcInfo.getStreamId(), mediaServerItem.getId(), okEvent.getClientTransaction());
  541 + streamSession.put(device.getDeviceId(), channelId, dialog);
  542 + });
553 543 } catch ( SipException | ParseException | InvalidArgumentException e) {
554 544 e.printStackTrace();
555 545 }
... ... @@ -565,30 +555,20 @@ public class SIPCommander implements ISIPCommander {
565 555 * @param downloadSpeed 下载倍速参数
566 556 */
567 557 @Override
568   - public void downloadStreamCmd(IMediaServerItem mediaServerItem,Device device, String channelId, String startTime, String endTime, String downloadSpeed, ZLMHttpHookSubscribe.Event event
  558 + public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, String startTime, String endTime, String downloadSpeed, ZLMHttpHookSubscribe.Event event
569 559 , SipSubscribe.Event errorEvent) {
570 560 try {
571   - String ssrc = streamSession.createPlayBackSsrc();
572   - String streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
573   -
574   - Integer mediaPort = null;
575   - // 使用动态udp端口
576   - if (mediaServerItem.isRtpEnable()) {
577   - mediaPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId);
578   - }else {
579   - mediaPort = mediaServerItem.getRtpProxyPort();
580   - }
581   - logger.info("{} 分配的ZLM为: {} [{}:{}]", streamId, mediaServerItem.getId(), mediaServerItem.getIp(), mediaPort);
  561 + logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStreamId(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
582 562  
583 563 // 添加订阅
584 564 JSONObject subscribeKey = new JSONObject();
585 565 subscribeKey.put("app", "rtp");
586   - subscribeKey.put("stream", streamId);
  566 + subscribeKey.put("stream", ssrcInfo.getStreamId());
587 567 subscribeKey.put("regist", true);
588 568 subscribeKey.put("mediaServerId", mediaServerItem.getId());
589 569 logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString());
590 570 subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
591   - (IMediaServerItem mediaServerItemInUse, JSONObject json)->{
  571 + (MediaServerItem mediaServerItemInUse, JSONObject json)->{
592 572 if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
593 573 event.response(mediaServerItemInUse, json);
594 574 subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
... ... @@ -609,11 +589,11 @@ public class SIPCommander implements ISIPCommander {
609 589  
610 590 if (userSetup.isSeniorSdp()) {
611 591 if("TCP-PASSIVE".equals(streamMode)) {
612   - content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
  592 + content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
613 593 }else if ("TCP-ACTIVE".equals(streamMode)) {
614   - content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
  594 + content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
615 595 }else if("UDP".equals(streamMode)) {
616   - content.append("m=video "+ mediaPort +" RTP/AVP 96 126 125 99 34 98 97\r\n");
  596 + content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 126 125 99 34 98 97\r\n");
617 597 }
618 598 content.append("a=recvonly\r\n");
619 599 content.append("a=rtpmap:96 PS/90000\r\n");
... ... @@ -634,11 +614,11 @@ public class SIPCommander implements ISIPCommander {
634 614 }
635 615 }else {
636 616 if("TCP-PASSIVE".equals(streamMode)) {
637   - content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 98 97\r\n");
  617 + content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n");
638 618 }else if ("TCP-ACTIVE".equals(streamMode)) {
639   - content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 98 97\r\n");
  619 + content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n");
640 620 }else if("UDP".equals(streamMode)) {
641   - content.append("m=video "+ mediaPort +" RTP/AVP 96 98 97\r\n");
  621 + content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 98 97\r\n");
642 622 }
643 623 content.append("a=recvonly\r\n");
644 624 content.append("a=rtpmap:96 PS/90000\r\n");
... ... @@ -654,7 +634,7 @@ public class SIPCommander implements ISIPCommander {
654 634 }
655 635 content.append("a=downloadspeed:" + downloadSpeed + "\r\n");
656 636  
657   - content.append("y="+ssrc+"\r\n");//ssrc
  637 + content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
658 638  
659 639 String tm = Long.toString(System.currentTimeMillis());
660 640  
... ... @@ -664,7 +644,7 @@ public class SIPCommander implements ISIPCommander {
664 644 Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader);
665 645  
666 646 ClientTransaction transaction = transmitRequest(device, request, errorEvent);
667   - streamSession.put(device.getDeviceId(), channelId, ssrc, streamId, transaction);
  647 + streamSession.put(device.getDeviceId(), channelId, ssrcInfo.getSsrc(), ssrcInfo.getStreamId(), mediaServerItem.getId(), transaction);
668 648  
669 649 } catch ( SipException | ParseException | InvalidArgumentException e) {
670 650 e.printStackTrace();
... ... @@ -684,53 +664,35 @@ public class SIPCommander implements ISIPCommander {
684 664 */
685 665 @Override
686 666 public void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent) {
687   - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
688 667 try {
689 668 ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId);
690   - // 服务重启后, 无法直接发送bye, 通过手动构建发送
691   -// if (transaction == null) {
692   -//
693   -// if (streamInfo != null) {
694   -// MediaServerItem mediaServerItem = redisCatchStorage.getMediaInfo(streamInfo.getMediaServerId());
695   -// JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaServerItem,streamInfo.getApp(), streamInfo.getStreamId());
696   -// if (mediaList != null) { // 仍在推流才发送
697   -// if (mediaList.getInteger("code") == 0) {
698   -// JSONArray data = mediaList.getJSONArray("data");
699   -// if (data != null && data.size() > 0) {
700   -// Device device = storager.queryVideoDevice(deviceId);
701   -// if (device != null) {
702   -// StreamInfo.TransactionInfo transactionInfo = streamInfo.getTransactionInfo();
703   -// try {
704   -// Request byteRequest = headerProvider.createByteRequest(device, channelId,
705   -// transactionInfo.branch,
706   -// transactionInfo.localTag,
707   -// transactionInfo.remoteTag,
708   -// transactionInfo.callId);
709   -// transmitRequest(device, byteRequest);
710   -// } catch (InvalidArgumentException e) {
711   -// e.printStackTrace();
712   -// }
713   -// }
714   -// }
715   -// }
716   -// }
717   -// redisCatchStorage.stopPlay(streamInfo);
718   -// }
719   -//
720   -// if (okEvent != null) {
721   -// okEvent.response(null);
722   -// }
723   -// return;
724   -// }
725 669 if (transaction == null) {
726 670 logger.warn("[ {} -> {}]停止视频流的时候发现事务已丢失", deviceId, channelId);
727 671 return;
728 672 }
729   - Dialog dialog = transaction.getDialog();
  673 + SIPDialog dialog = streamSession.getDialog(deviceId, channelId);
730 674 if (dialog == null) {
731 675 logger.warn("[ {} -> {}]停止视频流的时候发现对话已丢失", deviceId, channelId);
732 676 return;
733 677 }
  678 + SipStack sipStack = udpSipProvider.getSipStack();
  679 + SIPDialog sipDialog = ((SipStackImpl) sipStack).putDialog(dialog);
  680 + if (dialog != sipDialog) {
  681 + dialog = sipDialog;
  682 + }else {
  683 + dialog.setSipProvider(udpSipProvider);
  684 + try {
  685 + Field sipStackField = SIPDialog.class.getDeclaredField("sipStack");
  686 + sipStackField.setAccessible(true);
  687 + sipStackField.set(dialog, sipStack);
  688 + Field eventListenersField = SIPDialog.class.getDeclaredField("eventListeners");
  689 + eventListenersField.setAccessible(true);
  690 + eventListenersField.set(dialog, new HashSet<>());
  691 + } catch (NoSuchFieldException | IllegalAccessException e) {
  692 + e.printStackTrace();
  693 + }
  694 + }
  695 +
734 696 Request byeRequest = dialog.createRequest(Request.BYE);
735 697 SipURI byeURI = (SipURI) byeRequest.getRequestURI();
736 698 SIPRequest request = (SIPRequest)transaction.getRequest();
... ... @@ -752,7 +714,12 @@ public class SIPCommander implements ISIPCommander {
752 714  
753 715 dialog.sendRequest(clientTransaction);
754 716  
755   - streamSession.remove(deviceId, channelId);
  717 + SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(deviceId, channelId);
  718 + if (ssrcTransaction != null) {
  719 + MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransaction.getMediaServerId());
  720 + mediaServerService.releaseSsrc(mediaServerItem, ssrcTransaction.getSsrc());
  721 + streamSession.remove(deviceId, channelId);
  722 + }
756 723 } catch (SipException | ParseException e) {
757 724 e.printStackTrace();
758 725 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java
... ... @@ -13,7 +13,6 @@ import com.genersoft.iot.vmp.common.StreamInfo;
13 13 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
14 14 import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
15 15 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
16   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
17 16 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
18 17 import com.genersoft.iot.vmp.service.IMediaServerService;
19 18 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
... ... @@ -81,7 +80,7 @@ public class AckRequestProcessor extends SIPRequestAbstractProcessor {
81 80 while (!rtpPushed) {
82 81 try {
83 82 if (System.currentTimeMillis() - startTime < 30 * 1000) {
84   - IMediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
  83 + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
85 84 if (zlmrtpServerFactory.isStreamReady(mediaInfo, streamInfo.getApp(), streamInfo.getStreamId())) {
86 85 rtpPushed = true;
87 86 logger.info("已获取设备推流[{}/{}],开始向上级推流[{}:{}]",
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java
... ... @@ -15,7 +15,6 @@ import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
15 15 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
16 16 import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
17 17 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
18   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
19 18 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
20 19 import com.genersoft.iot.vmp.service.IMediaServerService;
21 20 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
... ... @@ -65,7 +64,7 @@ public class ByeRequestProcessor extends SIPRequestAbstractProcessor {
65 64 param.put("stream",streamId);
66 65 param.put("ssrc",sendRtpItem.getSsrc());
67 66 logger.info("停止向上级推流:" + streamId);
68   - IMediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
  67 + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
69 68 zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
70 69 redisCatchStorage.deleteSendRTPServer(platformGbId, channelId);
71 70 if (zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId) == 0) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java
... ... @@ -11,14 +11,11 @@ import javax.sip.header.*;
11 11 import javax.sip.message.Request;
12 12 import javax.sip.message.Response;
13 13  
14   -import com.genersoft.iot.vmp.common.StreamInfo;
15   -import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
16 14 import com.genersoft.iot.vmp.gb28181.bean.*;
17 15 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
18 16 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
19 17 import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
20 18 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
21   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
22 19 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
23 20 import com.genersoft.iot.vmp.service.IMediaServerService;
24 21 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
... ... @@ -97,7 +94,7 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
97 94 // 查询平台下是否有该通道
98 95 DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId);
99 96 GbStream gbStream = storager.queryStreamInParentPlatform(requesterId, channelId);
100   - IMediaServerItem mediaServerItem = null;
  97 + MediaServerItem mediaServerItem = null;
101 98 // 不是通道可能是直播流
102 99 if (channel != null && gbStream == null ) {
103 100 if (channel.getStatus() == 0) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/InviteResponseProcessor.java
... ... @@ -3,14 +3,18 @@ package com.genersoft.iot.vmp.gb28181.transmit.response.impl;
3 3 import java.text.ParseException;
4 4  
5 5 import javax.sip.*;
  6 +import javax.sip.address.Address;
6 7 import javax.sip.address.SipURI;
7 8 import javax.sip.header.CSeqHeader;
8 9 import javax.sip.message.Request;
9 10 import javax.sip.message.Response;
10 11  
  12 +import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
11 13 import gov.nist.javax.sip.ResponseEventExt;
  14 +import gov.nist.javax.sip.stack.SIPDialog;
12 15 import org.slf4j.Logger;
13 16 import org.slf4j.LoggerFactory;
  17 +import org.springframework.beans.factory.annotation.Autowired;
14 18 import org.springframework.stereotype.Component;
15 19  
16 20 import com.genersoft.iot.vmp.conf.SipConfig;
... ... @@ -28,6 +32,9 @@ public class InviteResponseProcessor implements ISIPResponseProcessor {
28 32  
29 33 private final static Logger logger = LoggerFactory.getLogger(InviteResponseProcessor.class);
30 34  
  35 + @Autowired
  36 + private VideoStreamSessionManager streamSession;
  37 +
31 38 /**
32 39 * 处理invite响应
33 40 *
... ... @@ -46,7 +53,7 @@ public class InviteResponseProcessor implements ISIPResponseProcessor {
46 53 // 下发ack
47 54 if (statusCode == Response.OK) {
48 55 ResponseEventExt event = (ResponseEventExt)evt;
49   - Dialog dialog = evt.getDialog();
  56 + SIPDialog dialog = (SIPDialog)evt.getDialog();
50 57 CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
51 58 Request reqAck = dialog.createAck(cseq.getSeqNumber());
52 59 SipURI requestURI = (SipURI) reqAck.getRequestURI();
... ... @@ -54,7 +61,12 @@ public class InviteResponseProcessor implements ISIPResponseProcessor {
54 61 requestURI.setPort(event.getRemotePort());
55 62 reqAck.setRequestURI(requestURI);
56 63 logger.info("向 " + event.getRemoteIpAddress() + ":" + event.getRemotePort() + "回复ack");
  64 + SipURI sipURI = (SipURI)dialog.getRemoteParty().getURI();
  65 + String deviceId = requestURI.getUser();
  66 + String channelId = sipURI.getUser();
  67 +
57 68 dialog.sendAck(reqAck);
  69 +
58 70 }
59 71 } catch (InvalidArgumentException | SipException e) {
60 72 e.printStackTrace();
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
... ... @@ -3,15 +3,14 @@ package com.genersoft.iot.vmp.media.zlm;
3 3 import java.util.List;
4 4 import java.util.UUID;
5 5  
6   -import com.alibaba.fastjson.JSON;
7 6 import com.alibaba.fastjson.JSONArray;
8 7 import com.genersoft.iot.vmp.common.StreamInfo;
9 8 import com.genersoft.iot.vmp.conf.MediaConfig;
10 9 import com.genersoft.iot.vmp.conf.UserSetup;
11 10 import com.genersoft.iot.vmp.gb28181.bean.Device;
12   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
13 11 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
14 12 import com.genersoft.iot.vmp.service.IMediaServerService;
  13 +import com.genersoft.iot.vmp.service.bean.SSRCInfo;
15 14 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
16 15 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
17 16 import com.genersoft.iot.vmp.service.IPlayService;
... ... @@ -42,7 +41,6 @@ public class ZLMHttpHookListener {
42 41  
43 42 private final static Logger logger = LoggerFactory.getLogger(ZLMHttpHookListener.class);
44 43  
45   -
46 44 @Autowired
47 45 private SIPCommander cmder;
48 46  
... ... @@ -125,7 +123,7 @@ public class ZLMHttpHookListener {
125 123 String mediaServerId = json.getString("mediaServerId");
126 124 ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_play, json);
127 125 if (subscribe != null ) {
128   - IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
  126 + MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
129 127 if (mediaInfo != null) {
130 128 subscribe.response(mediaInfo, json);
131 129 }
... ... @@ -150,7 +148,7 @@ public class ZLMHttpHookListener {
150 148 String mediaServerId = json.getString("mediaServerId");
151 149 ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_publish, json);
152 150 if (subscribe != null) {
153   - IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
  151 + MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
154 152 if (mediaInfo != null) {
155 153 subscribe.response(mediaInfo, json);
156 154 }
... ... @@ -237,7 +235,7 @@ public class ZLMHttpHookListener {
237 235 String mediaServerId = json.getString("mediaServerId");
238 236 ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_shell_login, json);
239 237 if (subscribe != null ) {
240   - IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
  238 + MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
241 239 if (mediaInfo != null) {
242 240 subscribe.response(mediaInfo, json);
243 241 }
... ... @@ -264,7 +262,7 @@ public class ZLMHttpHookListener {
264 262 String mediaServerId = json.getString("mediaServerId");
265 263 ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, json);
266 264 if (subscribe != null ) {
267   - IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
  265 + MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
268 266 if (mediaInfo != null) {
269 267 subscribe.response(mediaInfo, json);
270 268 }
... ... @@ -297,7 +295,7 @@ public class ZLMHttpHookListener {
297 295 }
298 296 }else {
299 297 if (!"rtp".equals(app) ){
300   - IMediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
  298 + MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
301 299 if (regist) {
302 300 zlmMediaListManager.addMedia(mediaServerItem, app, streamId);
303 301 }else {
... ... @@ -369,7 +367,7 @@ public class ZLMHttpHookListener {
369 367 logger.debug("ZLM HOOK on_stream_not_found API调用,参数:" + json.toString());
370 368 }
371 369 String mediaServerId = json.getString("mediaServerId");
372   - IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
  370 + MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
373 371 if (userSetup.isAutoApplyPlay() && mediaInfo != null) {
374 372 String app = json.getString("app");
375 373 String streamId = json.getString("stream");
... ... @@ -381,7 +379,13 @@ public class ZLMHttpHookListener {
381 379 Device device = storager.queryVideoDevice(deviceId);
382 380 if (device != null) {
383 381 UUID uuid = UUID.randomUUID();
384   - cmder.playStreamCmd(mediaInfo, device, channelId, (IMediaServerItem mediaServerItemInuse, JSONObject response) -> {
  382 + SSRCInfo ssrcInfo;
  383 + String streamId2 = null;
  384 + if (mediaInfo.isRtpEnable()) {
  385 + streamId2 = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
  386 + }
  387 + ssrcInfo = mediaServerService.openRTPServer(mediaInfo, streamId2);
  388 + cmder.playStreamCmd(mediaInfo, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> {
385 389 logger.info("收到订阅消息: " + response.toJSONString());
386 390 playService.onPublishHandlerForPlay(mediaServerItemInuse, response, deviceId, channelId, uuid.toString());
387 391 }, null);
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java
1 1 package com.genersoft.iot.vmp.media.zlm;
2 2  
3 3 import com.alibaba.fastjson.JSONObject;
4   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
5 4 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
6 5 import org.springframework.stereotype.Component;
7 6  
... ... @@ -32,7 +31,7 @@ public class ZLMHttpHookSubscribe {
32 31 }
33 32  
34 33 public interface Event{
35   - void response(IMediaServerItem mediaServerItem, JSONObject response);
  34 + void response(MediaServerItem mediaServerItem, JSONObject response);
36 35 }
37 36  
38 37 private Map<HookType, Map<JSONObject, ZLMHttpHookSubscribe.Event>> allSubscribes = new ConcurrentHashMap<>();
... ... @@ -58,6 +57,9 @@ public class ZLMHttpHookSubscribe {
58 57 if (result == null) {
59 58 result = key.getString(s).equals(hookResponse.getString(s));
60 59 }else {
  60 + if (key.getString(s) == null) {
  61 + continue;
  62 + }
61 63 result = result && key.getString(s).equals(hookResponse.getString(s));
62 64 }
63 65  
... ... @@ -83,9 +85,9 @@ public class ZLMHttpHookSubscribe {
83 85 if (result == null) {
84 86 result = key.getString(s).equals(hookResponse.getString(s));
85 87 }else {
  88 + if (key.getString(s) == null) continue;
86 89 result = result && key.getString(s).equals(hookResponse.getString(s));
87 90 }
88   -
89 91 }
90 92 if (null != result && result){
91 93 iterator.remove();
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java
1 1 package com.genersoft.iot.vmp.media.zlm;
2 2  
3   -import com.alibaba.fastjson.JSONArray;
4 3 import com.alibaba.fastjson.JSONObject;
5   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
6 4 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
7 5 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
8 6 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
9   -import com.genersoft.iot.vmp.gb28181.bean.GbStream;
10 7 import com.genersoft.iot.vmp.service.IStreamPushService;
11 8 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
12 9 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
... ... @@ -76,7 +73,7 @@ public class ZLMMediaListManager {
76 73 jsonObject.put("stream", streamPushItem.getStream());
77 74 jsonObject.put("mediaServerId", mediaServerItem.getId());
78 75 subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_play,jsonObject,
79   - (IMediaServerItem mediaServerItemInuse, JSONObject response)->{
  76 + (MediaServerItem mediaServerItemInuse, JSONObject response)->{
80 77 updateMedia(mediaServerItem, response.getString("app"), response.getString("stream"));
81 78 }
82 79 );
... ... @@ -86,13 +83,13 @@ public class ZLMMediaListManager {
86 83  
87 84 }
88 85  
89   - public void addMedia(IMediaServerItem mediaServerItem, String app, String streamId) {
  86 + public void addMedia(MediaServerItem mediaServerItem, String app, String streamId) {
90 87 //使用异步更新推流
91 88 updateMedia(mediaServerItem, app, streamId);
92 89 }
93 90  
94 91  
95   - public void updateMedia(IMediaServerItem mediaServerItem, String app, String streamId) {
  92 + public void updateMedia(MediaServerItem mediaServerItem, String app, String streamId) {
96 93 //使用异步更新推流
97 94 zlmresTfulUtils.getMediaList(mediaServerItem, app, streamId, "rtmp", json->{
98 95  
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java
... ... @@ -2,14 +2,11 @@ package com.genersoft.iot.vmp.media.zlm;
2 2  
3 3 import com.alibaba.fastjson.JSON;
4 4 import com.alibaba.fastjson.JSONObject;
5   -import com.genersoft.iot.vmp.conf.MediaConfig;
6   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
7 5 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
8 6 import okhttp3.*;
9 7 import org.jetbrains.annotations.NotNull;
10 8 import org.slf4j.Logger;
11 9 import org.slf4j.LoggerFactory;
12   -import org.springframework.beans.factory.annotation.Autowired;
13 10 import org.springframework.stereotype.Component;
14 11  
15 12 import java.io.*;
... ... @@ -27,7 +24,7 @@ public class ZLMRESTfulUtils {
27 24 void run(JSONObject response);
28 25 }
29 26  
30   - public JSONObject sendPost(IMediaServerItem mediaServerItem, String api, Map<String, Object> param, RequestCallback callback) {
  27 + public JSONObject sendPost(MediaServerItem mediaServerItem, String api, Map<String, Object> param, RequestCallback callback) {
31 28 OkHttpClient client = new OkHttpClient();
32 29 String url = String.format("http://%s:%s/index/api/%s", mediaServerItem.getIp(), mediaServerItem.getHttpPort(), api);
33 30 JSONObject responseJSON = null;
... ... @@ -93,7 +90,7 @@ public class ZLMRESTfulUtils {
93 90 }
94 91  
95 92  
96   - public void sendPostForImg(IMediaServerItem mediaServerItem, String api, Map<String, Object> param, String targetPath, String fileName) {
  93 + public void sendPostForImg(MediaServerItem mediaServerItem, String api, Map<String, Object> param, String targetPath, String fileName) {
97 94 OkHttpClient client = new OkHttpClient();
98 95 String url = String.format("http://%s:%s/index/api/%s", mediaServerItem.getIp(), mediaServerItem.getHttpPort(), api);
99 96 JSONObject responseJSON = null;
... ... @@ -139,7 +136,7 @@ public class ZLMRESTfulUtils {
139 136 }
140 137  
141 138  
142   - public JSONObject getMediaList(IMediaServerItem mediaServerItem,String app, String stream, String schema, RequestCallback callback){
  139 + public JSONObject getMediaList(MediaServerItem mediaServerItem, String app, String stream, String schema, RequestCallback callback){
143 140 Map<String, Object> param = new HashMap<>();
144 141 if (app != null) param.put("app",app);
145 142 if (stream != null) param.put("stream",stream);
... ... @@ -148,15 +145,15 @@ public class ZLMRESTfulUtils {
148 145 return sendPost(mediaServerItem, "getMediaList",param, callback);
149 146 }
150 147  
151   - public JSONObject getMediaList(IMediaServerItem mediaServerItem,String app, String stream){
  148 + public JSONObject getMediaList(MediaServerItem mediaServerItem, String app, String stream){
152 149 return getMediaList(mediaServerItem, app, stream,null, null);
153 150 }
154 151  
155   - public JSONObject getMediaList(IMediaServerItem mediaServerItem,RequestCallback callback){
  152 + public JSONObject getMediaList(MediaServerItem mediaServerItem, RequestCallback callback){
156 153 return sendPost(mediaServerItem, "getMediaList",null, callback);
157 154 }
158 155  
159   - public JSONObject getMediaInfo(IMediaServerItem mediaServerItem,String app, String schema, String stream){
  156 + public JSONObject getMediaInfo(MediaServerItem mediaServerItem, String app, String schema, String stream){
160 157 Map<String, Object> param = new HashMap<>();
161 158 param.put("app",app);
162 159 param.put("schema",schema);
... ... @@ -165,13 +162,13 @@ public class ZLMRESTfulUtils {
165 162 return sendPost(mediaServerItem, "getMediaInfo",param, null);
166 163 }
167 164  
168   - public JSONObject getRtpInfo(IMediaServerItem mediaServerItem,String stream_id){
  165 + public JSONObject getRtpInfo(MediaServerItem mediaServerItem, String stream_id){
169 166 Map<String, Object> param = new HashMap<>();
170 167 param.put("stream_id",stream_id);
171 168 return sendPost(mediaServerItem, "getRtpInfo",param, null);
172 169 }
173 170  
174   - public JSONObject addFFmpegSource(IMediaServerItem mediaServerItem,String src_url, String dst_url, String timeout_ms,
  171 + public JSONObject addFFmpegSource(MediaServerItem mediaServerItem, String src_url, String dst_url, String timeout_ms,
175 172 boolean enable_hls, boolean enable_mp4, String ffmpeg_cmd_key){
176 173 logger.info(src_url);
177 174 logger.info(dst_url);
... ... @@ -185,41 +182,41 @@ public class ZLMRESTfulUtils {
185 182 return sendPost(mediaServerItem, "addFFmpegSource",param, null);
186 183 }
187 184  
188   - public JSONObject delFFmpegSource(IMediaServerItem mediaServerItem,String key){
  185 + public JSONObject delFFmpegSource(MediaServerItem mediaServerItem, String key){
189 186 Map<String, Object> param = new HashMap<>();
190 187 param.put("key", key);
191 188 return sendPost(mediaServerItem, "delFFmpegSource",param, null);
192 189 }
193 190  
194   - public JSONObject getMediaServerConfig(IMediaServerItem mediaServerItem){
  191 + public JSONObject getMediaServerConfig(MediaServerItem mediaServerItem){
195 192 return sendPost(mediaServerItem, "getServerConfig",null, null);
196 193 }
197 194  
198   - public JSONObject setServerConfig(IMediaServerItem mediaServerItem, Map<String, Object> param){
  195 + public JSONObject setServerConfig(MediaServerItem mediaServerItem, Map<String, Object> param){
199 196 return sendPost(mediaServerItem,"setServerConfig",param, null);
200 197 }
201 198  
202   - public JSONObject openRtpServer(IMediaServerItem mediaServerItem,Map<String, Object> param){
  199 + public JSONObject openRtpServer(MediaServerItem mediaServerItem, Map<String, Object> param){
203 200 return sendPost(mediaServerItem, "openRtpServer",param, null);
204 201 }
205 202  
206   - public JSONObject closeRtpServer(IMediaServerItem mediaServerItem,Map<String, Object> param) {
  203 + public JSONObject closeRtpServer(MediaServerItem mediaServerItem, Map<String, Object> param) {
207 204 return sendPost(mediaServerItem, "closeRtpServer",param, null);
208 205 }
209 206  
210   - public JSONObject listRtpServer(IMediaServerItem mediaServerItem) {
  207 + public JSONObject listRtpServer(MediaServerItem mediaServerItem) {
211 208 return sendPost(mediaServerItem, "listRtpServer",null, null);
212 209 }
213 210  
214   - public JSONObject startSendRtp(IMediaServerItem mediaServerItem,Map<String, Object> param) {
  211 + public JSONObject startSendRtp(MediaServerItem mediaServerItem, Map<String, Object> param) {
215 212 return sendPost(mediaServerItem, "startSendRtp",param, null);
216 213 }
217 214  
218   - public JSONObject stopSendRtp(IMediaServerItem mediaServerItem,Map<String, Object> param) {
  215 + public JSONObject stopSendRtp(MediaServerItem mediaServerItem, Map<String, Object> param) {
219 216 return sendPost(mediaServerItem, "stopSendRtp",param, null);
220 217 }
221 218  
222   - public JSONObject addStreamProxy(IMediaServerItem mediaServerItem,String app, String stream, String url, boolean enable_hls, boolean enable_mp4, String rtp_type) {
  219 + public JSONObject addStreamProxy(MediaServerItem mediaServerItem, String app, String stream, String url, boolean enable_hls, boolean enable_mp4, String rtp_type) {
223 220 Map<String, Object> param = new HashMap<>();
224 221 param.put("vhost", "__defaultVhost__");
225 222 param.put("app", app);
... ... @@ -231,7 +228,7 @@ public class ZLMRESTfulUtils {
231 228 return sendPost(mediaServerItem, "addStreamProxy",param, null);
232 229 }
233 230  
234   - public JSONObject closeStreams(IMediaServerItem mediaServerItem,String app, String stream) {
  231 + public JSONObject closeStreams(MediaServerItem mediaServerItem, String app, String stream) {
235 232 Map<String, Object> param = new HashMap<>();
236 233 param.put("vhost", "__defaultVhost__");
237 234 param.put("app", app);
... ... @@ -240,17 +237,17 @@ public class ZLMRESTfulUtils {
240 237 return sendPost(mediaServerItem, "close_streams",param, null);
241 238 }
242 239  
243   - public JSONObject getAllSession(IMediaServerItem mediaServerItem) {
  240 + public JSONObject getAllSession(MediaServerItem mediaServerItem) {
244 241 return sendPost(mediaServerItem, "getAllSession",null, null);
245 242 }
246 243  
247   - public void kickSessions(IMediaServerItem mediaServerItem, String localPortSStr) {
  244 + public void kickSessions(MediaServerItem mediaServerItem, String localPortSStr) {
248 245 Map<String, Object> param = new HashMap<>();
249 246 param.put("local_port", localPortSStr);
250 247 sendPost(mediaServerItem, "kick_sessions",param, null);
251 248 }
252 249  
253   - public void getSnap(IMediaServerItem mediaServerItem, String flvUrl, int timeout_sec, int expire_sec, String targetPath, String fileName) {
  250 + public void getSnap(MediaServerItem mediaServerItem, String flvUrl, int timeout_sec, int expire_sec, String targetPath, String fileName) {
254 251 Map<String, Object> param = new HashMap<>();
255 252 param.put("url", flvUrl);
256 253 param.put("timeout_sec", timeout_sec);
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
... ... @@ -2,10 +2,7 @@ package com.genersoft.iot.vmp.media.zlm;
2 2  
3 3 import com.alibaba.fastjson.JSONArray;
4 4 import com.alibaba.fastjson.JSONObject;
5   -import com.genersoft.iot.vmp.conf.MediaConfig;
6 5 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
7   -import com.genersoft.iot.vmp.gb28181.session.SsrcUtil;
8   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
9 6 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
10 7 import org.slf4j.Logger;
11 8 import org.slf4j.LoggerFactory;
... ... @@ -21,28 +18,19 @@ public class ZLMRTPServerFactory {
21 18 private Logger logger = LoggerFactory.getLogger("ZLMRTPServerFactory");
22 19  
23 20 @Autowired
24   - private MediaConfig mediaConfig;
25   -
26   - @Autowired
27 21 private ZLMRESTfulUtils zlmresTfulUtils;
28 22  
29 23 private int[] portRangeArray = new int[2];
30 24  
31   - private int currentPort = 0;
32   -
33   - private Map<String, Integer> currentStreams = null;
34   -
35   - public int createRTPServer(IMediaServerItem mediaServerItem, String streamId) {
36   - if (currentStreams == null) {
37   - currentStreams = new HashMap<>();
38   - JSONObject jsonObject = zlmresTfulUtils.listRtpServer(mediaServerItem);
39   - if (jsonObject != null) {
40   - JSONArray data = jsonObject.getJSONArray("data");
41   - if (data != null) {
42   - for (int i = 0; i < data.size(); i++) {
43   - JSONObject dataItem = data.getJSONObject(i);
44   - currentStreams.put(dataItem.getString("stream_id"), dataItem.getInteger("port"));
45   - }
  25 + public int createRTPServer(MediaServerItem mediaServerItem, String streamId) {
  26 + Map<String, Integer> currentStreams = new HashMap<>();
  27 + JSONObject listRtpServerJsonResult = zlmresTfulUtils.listRtpServer(mediaServerItem);
  28 + if (listRtpServerJsonResult != null) {
  29 + JSONArray data = listRtpServerJsonResult.getJSONArray("data");
  30 + if (data != null) {
  31 + for (int i = 0; i < data.size(); i++) {
  32 + JSONObject dataItem = data.getJSONObject(i);
  33 + currentStreams.put(dataItem.getString("stream_id"), dataItem.getInteger("port"));
46 34 }
47 35 }
48 36 }
... ... @@ -56,18 +44,18 @@ public class ZLMRTPServerFactory {
56 44  
57 45 Map<String, Object> param = new HashMap<>();
58 46 int result = -1;
59   - int newPort = getPortFromportRange();
  47 + int newPort = getPortFromportRange(mediaServerItem);
60 48 param.put("port", newPort);
61 49 param.put("enable_tcp", 1);
62 50 param.put("stream_id", streamId);
63   - JSONObject jsonObject = zlmresTfulUtils.openRtpServer(mediaServerItem, param);
  51 + JSONObject openRtpServerResultJson = zlmresTfulUtils.openRtpServer(mediaServerItem, param);
64 52  
65   - if (jsonObject != null) {
66   - switch (jsonObject.getInteger("code")){
  53 + if (openRtpServerResultJson != null) {
  54 + switch (openRtpServerResultJson.getInteger("code")){
67 55 case 0:
68 56 result= newPort;
69 57 break;
70   - case -300: // id已经存在, 可能已经在其他端口推流
  58 + case -300: // id已经存在, 可能已经在其他端口推流, TODO 也可能是设备不等ack就直接推流了, 需要查询与设置的推流ip端口是否一致
71 59 Map<String, Object> closeRtpServerParam = new HashMap<>();
72 60 closeRtpServerParam.put("stream_id", streamId);
73 61 zlmresTfulUtils.closeRtpServer(mediaServerItem, closeRtpServerParam);
... ... @@ -77,7 +65,7 @@ public class ZLMRTPServerFactory {
77 65 result= createRTPServer(mediaServerItem, streamId);
78 66 break;
79 67 default:
80   - logger.error("创建RTP Server 失败 {}: " + jsonObject.getString("msg"), newPort);
  68 + logger.error("创建RTP Server 失败 {}: " + openRtpServerResultJson.getString("msg"), newPort);
81 69 break;
82 70 }
83 71 }else {
... ... @@ -87,7 +75,7 @@ public class ZLMRTPServerFactory {
87 75 return result;
88 76 }
89 77  
90   - public boolean closeRTPServer(IMediaServerItem serverItem, String streamId) {
  78 + public boolean closeRTPServer(MediaServerItem serverItem, String streamId) {
91 79 boolean result = false;
92 80 if (serverItem !=null){
93 81 Map<String, Object> param = new HashMap<>();
... ... @@ -107,21 +95,25 @@ public class ZLMRTPServerFactory {
107 95 return result;
108 96 }
109 97  
110   - private int getPortFromportRange() {
  98 + private int getPortFromportRange(MediaServerItem mediaServerItem) {
  99 + int currentPort = mediaServerItem.getCurrentPort();
111 100 if (currentPort == 0) {
112   - String[] portRangeStrArray = mediaConfig.getRtpPortRange().split(",");
  101 + String[] portRangeStrArray = mediaServerItem.getRtpPortRange().split(",");
113 102 portRangeArray[0] = Integer.parseInt(portRangeStrArray[0]);
114 103 portRangeArray[1] = Integer.parseInt(portRangeStrArray[1]);
115 104 }
116 105  
117 106 if (currentPort == 0 || currentPort++ > portRangeArray[1]) {
118 107 currentPort = portRangeArray[0];
  108 + mediaServerItem.setCurrentPort(currentPort);
119 109 return portRangeArray[0];
120 110 } else {
121 111 if (currentPort % 2 == 1) {
122 112 currentPort++;
123 113 }
124   - return currentPort++;
  114 + currentPort++;
  115 + mediaServerItem.setCurrentPort(currentPort);
  116 + return currentPort;
125 117 }
126 118 }
127 119  
... ... @@ -135,10 +127,14 @@ public class ZLMRTPServerFactory {
135 127 * @param tcp 是否为tcp
136 128 * @return SendRtpItem
137 129 */
138   - public SendRtpItem createSendRtpItem(IMediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String deviceId, String channelId, boolean tcp){
139   - String playSsrc = SsrcUtil.getPlaySsrc();
140   - int localPort = createRTPServer(serverItem, SsrcUtil.getPlaySsrc());
  130 + public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String deviceId, String channelId, boolean tcp){
  131 +
  132 + // 使用RTPServer 功能找一个可用的端口
  133 + String playSsrc = serverItem.getSsrcConfig().getPlaySsrc();
  134 + int localPort = createRTPServer(serverItem, playSsrc);
141 135 if (localPort != -1) {
  136 + // TODO 高并发时可能因为未放入缓存而ssrc冲突
  137 + serverItem.getSsrcConfig().releaseSsrc(playSsrc);
142 138 closeRTPServer(serverItem, playSsrc);
143 139 }else {
144 140 logger.error("没有可用的端口");
... ... @@ -168,10 +164,12 @@ public class ZLMRTPServerFactory {
168 164 * @param tcp 是否为tcp
169 165 * @return SendRtpItem
170 166 */
171   - public SendRtpItem createSendRtpItem(IMediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String app, String stream, String channelId, boolean tcp){
172   - String playSsrc = SsrcUtil.getPlaySsrc();
173   - int localPort = createRTPServer(serverItem, SsrcUtil.getPlaySsrc());
  167 + public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String app, String stream, String channelId, boolean tcp){
  168 + String playSsrc = serverItem.getSsrcConfig().getPlaySsrc();
  169 + int localPort = createRTPServer(serverItem, playSsrc);
174 170 if (localPort != -1) {
  171 + // TODO 高并发时可能因为未放入缓存而ssrc冲突
  172 + serverItem.getSsrcConfig().releaseSsrc(ssrc);
175 173 closeRTPServer(serverItem, playSsrc);
176 174 }else {
177 175 logger.error("没有可用的端口");
... ... @@ -194,7 +192,7 @@ public class ZLMRTPServerFactory {
194 192 /**
195 193 * 调用zlm RESTful API —— startSendRtp
196 194 */
197   - public Boolean startSendRtpStream(IMediaServerItem mediaServerItem, Map<String, Object>param) {
  195 + public Boolean startSendRtpStream(MediaServerItem mediaServerItem, Map<String, Object>param) {
198 196 Boolean result = false;
199 197 JSONObject jsonObject = zlmresTfulUtils.startSendRtp(mediaServerItem, param);
200 198 if (jsonObject == null) {
... ... @@ -219,7 +217,7 @@ public class ZLMRTPServerFactory {
219 217 /**
220 218 * 查询待转推的流是否就绪
221 219 */
222   - public Boolean isStreamReady(IMediaServerItem mediaServerItem, String app, String streamId) {
  220 + public Boolean isStreamReady(MediaServerItem mediaServerItem, String app, String streamId) {
223 221 JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtmp", streamId);
224 222 return (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online"));
225 223 }
... ... @@ -229,7 +227,7 @@ public class ZLMRTPServerFactory {
229 227 * @param streamId
230 228 * @return
231 229 */
232   - public int totalReaderCount(IMediaServerItem mediaServerItem, String app, String streamId) {
  230 + public int totalReaderCount(MediaServerItem mediaServerItem, String app, String streamId) {
233 231 JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtmp", streamId);
234 232 return mediaInfo.getInteger("totalReaderCount");
235 233 }
... ... @@ -237,7 +235,7 @@ public class ZLMRTPServerFactory {
237 235 /**
238 236 * 调用zlm RESTful API —— stopSendRtp
239 237 */
240   - public Boolean stopSendRtpStream(IMediaServerItem mediaServerItem,Map<String, Object>param) {
  238 + public Boolean stopSendRtpStream(MediaServerItem mediaServerItem, Map<String, Object>param) {
241 239 Boolean result = false;
242 240 JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(mediaServerItem, param);
243 241 if (jsonObject == null) {
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java
... ... @@ -4,22 +4,16 @@ import com.alibaba.fastjson.JSON;
4 4 import com.alibaba.fastjson.JSONArray;
5 5 import com.alibaba.fastjson.JSONObject;
6 6 import com.genersoft.iot.vmp.conf.MediaConfig;
7   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
8 7 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
9   -import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
10 8 import com.genersoft.iot.vmp.service.IMediaServerService;
11   -import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
12 9 import com.genersoft.iot.vmp.service.IStreamProxyService;
13 10 import org.slf4j.Logger;
14 11 import org.slf4j.LoggerFactory;
15 12 import org.springframework.beans.factory.annotation.Autowired;
16   -import org.springframework.beans.factory.annotation.Value;
17 13 import org.springframework.boot.CommandLineRunner;
18 14 import org.springframework.core.annotation.Order;
19 15 import org.springframework.stereotype.Component;
20   -import org.springframework.util.StringUtils;
21 16  
22   -import javax.print.attribute.standard.Media;
23 17 import java.util.*;
24 18  
25 19 @Component
... ... @@ -47,16 +41,26 @@ public class ZLMRunner implements CommandLineRunner {
47 41  
48 42 @Override
49 43 public void run(String... strings) throws Exception {
50   - IMediaServerItem presetMediaServer = mediaServerService.getOneByHostAndPort(
  44 + // 清楚redis缓存的在线zlm信息
  45 + mediaServerService.clearMediaServerForOnline();
  46 +
  47 + // 将配置文件的meida配置写入数据库
  48 + MediaServerItem presetMediaServer = mediaServerService.getOneByHostAndPort(
51 49 mediaConfig.getIp(), mediaConfig.getHttpPort());
52 50 if (presetMediaServer != null) {
53   - mediaConfig.setId(presetMediaServer.getId());
54   - mediaServerService.update(mediaConfig);
  51 + MediaServerItem mediaSerItem = mediaConfig.getMediaSerItem();
  52 + mediaSerItem.setId(presetMediaServer.getId());
  53 + mediaServerService.update(mediaSerItem);
  54 + }else {
  55 + if (mediaConfig.getId() != null) {
  56 + MediaServerItem mediaSerItem = mediaConfig.getMediaSerItem();
  57 + mediaServerService.add(mediaSerItem);
  58 + }
55 59 }
56 60  
57 61 // 订阅 zlm启动事件, 新的zlm也会从这里进入系统
58 62 hookSubscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_server_started,null,
59   - (IMediaServerItem mediaServerItem, JSONObject response)->{
  63 + (MediaServerItem mediaServerItem, JSONObject response)->{
60 64 ZLMServerConfig zlmServerConfig = JSONObject.toJavaObject(response, ZLMServerConfig.class);
61 65 if (zlmServerConfig !=null ) {
62 66 startGetMedia.remove(zlmServerConfig.getGeneralMediaServerId());
... ... @@ -69,23 +73,25 @@ public class ZLMRunner implements CommandLineRunner {
69 73 logger.info("等待默认zlm接入...");
70 74  
71 75 // 获取所有的zlm, 并开启主动连接
72   - List<IMediaServerItem> all = mediaServerService.getAll();
  76 + List<MediaServerItem> all = mediaServerService.getAll();
73 77 if (presetMediaServer == null) {
74 78 all.add(mediaConfig.getMediaSerItem());
75 79 }
76   - for (IMediaServerItem mediaServerItem : all) {
  80 + for (MediaServerItem mediaServerItem : all) {
77 81 if (startGetMedia == null) startGetMedia = new HashMap<>();
78 82 startGetMedia.put(mediaServerItem.getId(), true);
79 83 new Thread(() -> {
80 84 ZLMServerConfig zlmServerConfig = getMediaServerConfig(mediaServerItem);
81 85 if (zlmServerConfig != null) {
  86 + zlmServerConfig.setIp(mediaServerItem.getIp());
  87 + zlmServerConfig.setHttpPort(mediaServerItem.getHttpPort());
82 88 startGetMedia.remove(mediaServerItem.getId());
83 89 mediaServerService.handLeZLMServerConfig(zlmServerConfig);
84 90 }
85 91 }).start();
86 92 }
87 93 Timer timer = new Timer();
88   - // 1分钟后未连接到则不再去主动连接
  94 + // 2分钟后未连接到则不再去主动连接, TODO 并对重启前使用此在zlm的通道发送bye
89 95 timer.schedule(new TimerTask() {
90 96 @Override
91 97 public void run() {
... ... @@ -100,7 +106,7 @@ public class ZLMRunner implements CommandLineRunner {
100 106 }, 60 * 1000 * 2);
101 107 }
102 108  
103   - public ZLMServerConfig getMediaServerConfig(IMediaServerItem mediaServerItem) {
  109 + public ZLMServerConfig getMediaServerConfig(MediaServerItem mediaServerItem) {
104 110 if ( startGetMedia.get(mediaServerItem.getId()) == null || !startGetMedia.get(mediaServerItem.getId())) return null;
105 111 JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem);
106 112 ZLMServerConfig ZLMServerConfig = null;
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/IMediaServerItem.java deleted 100644 → 0
1   -package com.genersoft.iot.vmp.media.zlm.dto;
2   -
3   -public interface IMediaServerItem {
4   -
5   - String getId();
6   -
7   - void setId(String id);
8   -
9   - String getIp();
10   -
11   - void setIp(String ip);
12   -
13   - String getHookIp();
14   -
15   - void setHookIp(String hookIp);
16   -
17   - String getSdpIp();
18   -
19   - void setSdpIp(String sdpIp);
20   -
21   - String getStreamIp();
22   -
23   - void setStreamIp(String streamIp);
24   -
25   - int getHttpPort();
26   -
27   - void setHttpPort(int httpPort);
28   -
29   - int getHttpSSlPort();
30   -
31   - void setHttpSSlPort(int httpSSlPort);
32   -
33   - int getRtmpPort();
34   -
35   - void setRtmpPort(int rtmpPort);
36   -
37   - int getRtmpSSlPort();
38   -
39   - void setRtmpSSlPort(int rtmpSSlPort);
40   -
41   - int getRtpProxyPort();
42   -
43   - void setRtpProxyPort(int rtpProxyPort);
44   -
45   - int getRtspPort();
46   -
47   - void setRtspPort(int rtspPort);
48   -
49   - int getRtspSSLPort();
50   -
51   - void setRtspSSLPort(int rtspSSLPort);
52   -
53   - boolean isAutoConfig();
54   -
55   - void setAutoConfig(boolean autoConfig);
56   -
57   - String getSecret();
58   -
59   - void setSecret(String secret);
60   -
61   - String getStreamNoneReaderDelayMS();
62   -
63   - void setStreamNoneReaderDelayMS(String streamNoneReaderDelayMS);
64   -
65   - boolean isRtpEnable();
66   -
67   - void setRtpEnable(boolean rtpEnable);
68   -
69   - String getRtpPortRange();
70   -
71   - void setRtpPortRange(String rtpPortRange);
72   -
73   - int getRecordAssistPort();
74   -
75   - void setRecordAssistPort(int recordAssistPort);
76   -
77   - boolean isDocker();
78   -
79   - void setDocker(boolean docker);
80   -
81   - String getUpdateTime();
82   -
83   - void setUpdateTime(String updateTime);
84   -
85   - String getCreateTime();
86   -
87   - void setCreateTime(String createTime);
88   -
89   - int getCount();
90   -
91   - void setCount(int count);
92   -}
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java
1 1 package com.genersoft.iot.vmp.media.zlm.dto;
2 2  
3 3  
  4 +import com.genersoft.iot.vmp.gb28181.session.SsrcConfig;
4 5 import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
5 6 import org.springframework.util.StringUtils;
6 7  
7   -public class MediaServerItem implements IMediaServerItem{
  8 +import java.util.HashMap;
  9 +
  10 +public class MediaServerItem{
8 11  
9 12 private String id;
10 13  
... ... @@ -46,9 +49,18 @@ public class MediaServerItem implements IMediaServerItem{
46 49  
47 50 private String updateTime;
48 51  
49   - private boolean docker;
  52 + private boolean defaultServer;
  53 +
  54 + private SsrcConfig ssrcConfig;
  55 +
  56 + private int currentPort;
  57 +
50 58  
51   - private int count;
  59 + /**
  60 + * 每一台ZLM都有一套独立的SSRC列表
  61 + * 在ApplicationCheckRunner里对mediaServerSsrcMap进行初始化
  62 + */
  63 + private HashMap<String, SsrcConfig> mediaServerSsrcMap;
52 64  
53 65 public MediaServerItem() {
54 66 }
... ... @@ -218,14 +230,12 @@ public class MediaServerItem implements IMediaServerItem{
218 230 this.recordAssistPort = recordAssistPort;
219 231 }
220 232  
221   - @Override
222   - public boolean isDocker() {
223   - return docker;
  233 + public boolean isDefaultServer() {
  234 + return defaultServer;
224 235 }
225 236  
226   - @Override
227   - public void setDocker(boolean docker) {
228   - this.docker = docker;
  237 + public void setDefaultServer(boolean defaultServer) {
  238 + this.defaultServer = defaultServer;
229 239 }
230 240  
231 241 public String getCreateTime() {
... ... @@ -244,11 +254,29 @@ public class MediaServerItem implements IMediaServerItem{
244 254 this.updateTime = updateTime;
245 255 }
246 256  
247   - public int getCount() {
248   - return count;
  257 + public HashMap<String, SsrcConfig> getMediaServerSsrcMap() {
  258 + return mediaServerSsrcMap;
  259 + }
  260 +
  261 + public void setMediaServerSsrcMap(HashMap<String, SsrcConfig> mediaServerSsrcMap) {
  262 + this.mediaServerSsrcMap = mediaServerSsrcMap;
  263 + }
  264 +
  265 + public SsrcConfig getSsrcConfig() {
  266 + return ssrcConfig;
  267 + }
  268 +
  269 + public void setSsrcConfig(SsrcConfig ssrcConfig) {
  270 + this.ssrcConfig = ssrcConfig;
249 271 }
250 272  
251   - public void setCount(int count) {
252   - this.count = count;
  273 + public int getCurrentPort() {
  274 + return currentPort;
253 275 }
  276 +
  277 + public void setCurrentPort(int currentPort) {
  278 + this.currentPort = currentPort;
  279 + }
  280 +
  281 +
254 282 }
... ...
src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java
... ... @@ -3,8 +3,8 @@ package com.genersoft.iot.vmp.service;
3 3 import com.genersoft.iot.vmp.conf.MediaConfig;
4 4 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 5 import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
6   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
7 6 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
  7 +import com.genersoft.iot.vmp.service.bean.SSRCInfo;
8 8  
9 9 import java.util.List;
10 10  
... ... @@ -13,11 +13,13 @@ import java.util.List;
13 13 */
14 14 public interface IMediaServerService {
15 15  
16   - List<IMediaServerItem> getAll();
  16 + List<MediaServerItem> getAll();
17 17  
18   - IMediaServerItem getOne(String generalMediaServerId);
  18 + List<MediaServerItem> getAllOnline();
19 19  
20   - IMediaServerItem getOneByHostAndPort(String host, int port);
  20 + MediaServerItem getOne(String generalMediaServerId);
  21 +
  22 + MediaServerItem getOneByHostAndPort(String host, int port);
21 23  
22 24 /**
23 25 * 新的节点加入
... ... @@ -26,19 +28,27 @@ public interface IMediaServerService {
26 28 */
27 29 void handLeZLMServerConfig(ZLMServerConfig zlmServerConfig);
28 30  
29   - void updateServerCatch(IMediaServerItem mediaServerItem, Integer count, Boolean b);
30   -
31   - IMediaServerItem getMediaServerForMinimumLoad();
  31 + MediaServerItem getMediaServerForMinimumLoad();
32 32  
33   - void setZLMConfig(IMediaServerItem mediaServerItem);
  33 + void setZLMConfig(MediaServerItem mediaServerItem);
34 34  
35   - void init();
  35 + SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId);
36 36  
37 37 void closeRTPServer(Device device, String channelId);
38 38  
39   - void update(MediaConfig mediaConfig);
  39 + void clearRTPServer(MediaServerItem mediaServerItem);
  40 +
  41 + void update(MediaServerItem mediaSerItem);
40 42  
41 43 void addCount(String mediaServerId);
42 44  
43 45 void removeCount(String mediaServerId);
  46 +
  47 + void releaseSsrc(MediaServerItem mediaServerItem, String ssrc);
  48 +
  49 + void clearMediaServerForOnline();
  50 +
  51 + void add(MediaServerItem mediaSerItem);
  52 +
  53 + void resetOnlineServerItem(MediaServerItem serverItem);
44 54 }
... ...
src/main/java/com/genersoft/iot/vmp/service/IMediaService.java
... ... @@ -2,7 +2,6 @@ package com.genersoft.iot.vmp.service;
2 2  
3 3 import com.alibaba.fastjson.JSONArray;
4 4 import com.genersoft.iot.vmp.common.StreamInfo;
5   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
6 5 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
7 6  
8 7 /**
... ... @@ -33,7 +32,7 @@ public interface IMediaService {
33 32 * @param stream
34 33 * @return
35 34 */
36   - StreamInfo getStreamInfoByAppAndStream(IMediaServerItem mediaServerItem, String app, String stream, JSONArray tracks);
  35 + StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaServerItem, String app, String stream, JSONArray tracks);
37 36  
38 37 /**
39 38 * 根据应用名和流ID获取播放地址, 只是地址拼接,返回的ip使用远程访问ip,适用与zlm与wvp在一台主机的情况
... ... @@ -41,5 +40,5 @@ public interface IMediaService {
41 40 * @param stream
42 41 * @return
43 42 */
44   - StreamInfo getStreamInfoByAppAndStream(IMediaServerItem mediaInfo, String app, String stream, JSONArray tracks, String addr);
  43 + StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, JSONArray tracks, String addr);
45 44 }
... ...
src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
... ... @@ -4,7 +4,6 @@ import com.alibaba.fastjson.JSONObject;
4 4 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 5 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
6 6 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
7   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
8 7 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
9 8 import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
10 9  
... ... @@ -13,10 +12,10 @@ import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
13 12 */
14 13 public interface IPlayService {
15 14  
16   - void onPublishHandlerForPlayBack(IMediaServerItem mediaServerItem,JSONObject resonse, String deviceId, String channelId, String uuid);
17   - void onPublishHandlerForPlay(IMediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid);
  15 + void onPublishHandlerForPlayBack(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid);
  16 + void onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid);
18 17  
19   - PlayResult play(IMediaServerItem mediaServerItem, String deviceId, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
  18 + PlayResult play(MediaServerItem mediaServerItem, String deviceId, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
20 19  
21   - IMediaServerItem getNewMediaServerItem(Device device);
  20 + MediaServerItem getNewMediaServerItem(Device device);
22 21 }
... ...
src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java
1 1 package com.genersoft.iot.vmp.service;
2 2  
3 3 import com.alibaba.fastjson.JSONObject;
4   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
5 4 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
6 5 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
7 6 import com.github.pagehelper.PageInfo;
... ... @@ -63,5 +62,5 @@ public interface IStreamProxyService {
63 62 * 获取ffmpeg.cmd模板
64 63 * @return
65 64 */
66   - JSONObject getFFmpegCMDs(IMediaServerItem mediaServerItem);
  65 + JSONObject getFFmpegCMDs(MediaServerItem mediaServerItem);
67 66 }
... ...
src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java
1 1 package com.genersoft.iot.vmp.service;
2 2  
3 3 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
4   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
  4 +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
5 5 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
6 6 import com.github.pagehelper.PageInfo;
7 7  
... ... @@ -9,7 +9,7 @@ import java.util.List;
9 9  
10 10 public interface IStreamPushService {
11 11  
12   - List<StreamPushItem> handleJSON(String json, IMediaServerItem mediaServerItem);
  12 + List<StreamPushItem> handleJSON(String json, MediaServerItem mediaServerItem);
13 13  
14 14 /**
15 15 * 将应用名和流ID加入国标关联
... ...
src/main/java/com/genersoft/iot/vmp/service/bean/SSRCInfo.java 0 → 100644
  1 +package com.genersoft.iot.vmp.service.bean;
  2 +
  3 +public class SSRCInfo {
  4 +
  5 + private int port;
  6 + private String ssrc;
  7 + private String StreamId;
  8 +
  9 + public SSRCInfo(int port, String ssrc, String streamId) {
  10 + this.port = port;
  11 + this.ssrc = ssrc;
  12 + StreamId = streamId;
  13 + }
  14 +
  15 + public int getPort() {
  16 + return port;
  17 + }
  18 +
  19 + public void setPort(int port) {
  20 + this.port = port;
  21 + }
  22 +
  23 + public String getSsrc() {
  24 + return ssrc;
  25 + }
  26 +
  27 + public void setSsrc(String ssrc) {
  28 + this.ssrc = ssrc;
  29 + }
  30 +
  31 + public String getStreamId() {
  32 + return StreamId;
  33 + }
  34 +
  35 + public void setStreamId(String streamId) {
  36 + StreamId = streamId;
  37 + }
  38 +}
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
1 1 package com.genersoft.iot.vmp.service.impl;
2 2  
3   -import com.alibaba.fastjson.JSON;
4 3 import com.alibaba.fastjson.JSONArray;
5 4 import com.alibaba.fastjson.JSONObject;
6   -import com.genersoft.iot.vmp.common.StreamInfo;
  5 +import com.genersoft.iot.vmp.common.VideoManagerConstants;
7 6 import com.genersoft.iot.vmp.conf.MediaConfig;
8   -import com.genersoft.iot.vmp.conf.ProxyServletConfig;
  7 +import com.genersoft.iot.vmp.conf.SipConfig;
9 8 import com.genersoft.iot.vmp.gb28181.bean.Device;
  9 +import com.genersoft.iot.vmp.gb28181.session.SsrcConfig;
10 10 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
11 11 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
12 12 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
13 13 import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
14   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
15 14 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
16   -import com.genersoft.iot.vmp.media.zlm.dto.ZLMRunInfo;
17 15 import com.genersoft.iot.vmp.service.IMediaServerService;
  16 +import com.genersoft.iot.vmp.service.bean.SSRCInfo;
18 17 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
19 18 import com.genersoft.iot.vmp.storager.dao.MediaServerMapper;
20   -import org.mitre.dsmiley.httpproxy.ProxyServlet;
  19 +import com.genersoft.iot.vmp.utils.redis.JedisUtil;
  20 +import com.genersoft.iot.vmp.utils.redis.RedisUtil;
21 21 import org.slf4j.Logger;
22 22 import org.slf4j.LoggerFactory;
23 23 import org.springframework.beans.factory.annotation.Autowired;
24 24 import org.springframework.beans.factory.annotation.Value;
  25 +import org.springframework.boot.CommandLineRunner;
  26 +import org.springframework.core.annotation.Order;
25 27 import org.springframework.stereotype.Service;
26 28  
  29 +import java.sql.Array;
27 30 import java.text.SimpleDateFormat;
28 31 import java.util.*;
29 32  
... ... @@ -31,15 +34,13 @@ import java.util.*;
31 34 * 媒体服务器节点管理
32 35 */
33 36 @Service
34   -public class MediaServerServiceImpl implements IMediaServerService {
  37 +@Order(value=2)
  38 +public class MediaServerServiceImpl implements IMediaServerService, CommandLineRunner {
35 39  
36 40 private final static Logger logger = LoggerFactory.getLogger(MediaServerServiceImpl.class);
37 41  
38   - private Map<String, IMediaServerItem> zlmServers = new HashMap<>(); // 所有数据库的zlm的缓存
39   - private Map<String, Integer> zlmServerStatus = new LinkedHashMap<>(); // 所有上线的zlm的缓存以及负载
40   -
41   - @Value("${sip.ip}")
42   - private String sipIp;
  42 + @Autowired
  43 + private SipConfig sipConfig;
43 44  
44 45 @Value("${server.ssl.enabled:false}")
45 46 private boolean sslEnabled;
... ... @@ -56,7 +57,6 @@ public class MediaServerServiceImpl implements IMediaServerService {
56 57 @Autowired
57 58 private MediaServerMapper mediaServerMapper;
58 59  
59   -
60 60 @Autowired
61 61 private IRedisCatchStorage redisCatchStorage;
62 62  
... ... @@ -66,53 +66,134 @@ public class MediaServerServiceImpl implements IMediaServerService {
66 66 @Autowired
67 67 private ZLMRTPServerFactory zlmrtpServerFactory;
68 68  
69   - private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  69 + @Autowired
  70 + private RedisUtil redisUtil;
  71 +
  72 + @Autowired
  73 + JedisUtil jedisUtil;
  74 +
  75 + private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
70 76  
71 77 /**
72 78 * 初始化
73 79 */
74 80 @Override
75   - public void init() {
76   - zlmServers.clear();
77   - zlmServerStatus.clear();
  81 + public void run(String... args) throws Exception {
  82 + logger.info("Media Server 缓存初始化");
78 83 List<MediaServerItem> mediaServerItemList = mediaServerMapper.queryAll();
79   - for (IMediaServerItem mediaServerItem : mediaServerItemList) {
80   - zlmServers.put(mediaServerItem.getId(), mediaServerItem);
  84 + for (MediaServerItem mediaServerItem : mediaServerItemList) {
  85 + // 更新
  86 + if (mediaServerItem.getSsrcConfig() == null) {
  87 + SsrcConfig ssrcConfig = new SsrcConfig(mediaServerItem.getId(), null, sipConfig.getSipDomain());
  88 + mediaServerItem.setSsrcConfig(ssrcConfig);
  89 + redisUtil.set(VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerItem.getId(), mediaServerItem);
  90 + }
  91 + // 查询redis是否存在此mediaServer
  92 + String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerItem.getId();
  93 + if (!redisUtil.hasKey(key)) {
  94 + redisUtil.set(key, mediaServerItem);
  95 + }
  96 + }
  97 + }
  98 +
  99 + @Override
  100 + public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId) {
  101 + if (mediaServerItem == null || mediaServerItem.getId() == null) return null;
  102 + // 获取mediaServer可用的ssrc
  103 + String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerItem.getId();
  104 +
  105 + SsrcConfig ssrcConfig = mediaServerItem.getSsrcConfig();
  106 + if (ssrcConfig == null) {
  107 + logger.info("media server [ {} ] ssrcConfig is null", mediaServerItem.getId());
  108 + return null;
  109 + }else {
  110 + String ssrc = ssrcConfig.getPlaySsrc();
  111 + if (streamId == null) streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
  112 + int rtpServerPort = mediaServerItem.getRtpProxyPort();
  113 + if (mediaServerItem.isRtpEnable()) {
  114 + rtpServerPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId);
  115 + }
  116 + redisUtil.set(key, mediaServerItem);
  117 + return new SSRCInfo(rtpServerPort, ssrc, streamId);
81 118 }
82 119 }
83 120  
84 121 @Override
85 122 public void closeRTPServer(Device device, String channelId) {
86   - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId);
87   - IMediaServerItem mediaServerItem = null;
88   - if (streamInfo != null) {
89   - mediaServerItem = this.getOne (streamInfo.getMediaServerId());
  123 + String mediaServerId = streamSession.getMediaServerId(device.getDeviceId(), channelId);
  124 + MediaServerItem mediaServerItem = this.getOne(mediaServerId);
  125 + if (mediaServerItem != null) {
  126 + String streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
  127 + zlmrtpServerFactory.closeRTPServer(mediaServerItem, streamId);
  128 + releaseSsrc(mediaServerItem, streamSession.getSSRC(device.getDeviceId(), channelId));
90 129 }
91   - String streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
92   - zlmrtpServerFactory.closeRTPServer(mediaServerItem, streamId);
93 130 streamSession.remove(device.getDeviceId(), channelId);
94 131 }
95 132  
96 133 @Override
97   - public void update(MediaConfig mediaConfig) {
  134 + public void releaseSsrc(MediaServerItem mediaServerItem, String ssrc) {
  135 + if (mediaServerItem == null || ssrc == null) return;
  136 + SsrcConfig ssrcConfig = mediaServerItem.getSsrcConfig();
  137 + ssrcConfig.releaseSsrc(ssrc);
  138 + mediaServerItem.setSsrcConfig(ssrcConfig);
  139 + String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerItem.getId();
  140 + redisUtil.set(key, mediaServerItem);
  141 + }
98 142  
  143 + /**
  144 + * zlm 重启后重置他的推流信息, TODO 给正在使用的设备发送停止命令
  145 + * @param mediaServerItem
  146 + */
  147 + @Override
  148 + public void clearRTPServer(MediaServerItem mediaServerItem) {
  149 + mediaServerItem.setSsrcConfig(new SsrcConfig(mediaServerItem.getId(), null, sipConfig.getSipDomain()));
  150 + redisUtil.zAdd(VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX, mediaServerItem.getId(), 0);
99 151 }
100 152  
  153 +
101 154 @Override
102   - public List<IMediaServerItem> getAll() {
103   - if (zlmServers.size() == 0) {
104   - init();
  155 + public void update(MediaServerItem mediaSerItem) {
  156 + mediaServerMapper.update(mediaSerItem);
  157 + MediaServerItem mediaServerItemInRedis = getOne(mediaSerItem.getId());
  158 + MediaServerItem mediaServerItemInDataBase = mediaServerMapper.queryOne(mediaSerItem.getId());
  159 + if (mediaServerItemInRedis != null && mediaServerItemInRedis.getSsrcConfig() != null) {
  160 + mediaServerItemInDataBase.setSsrcConfig(mediaServerItemInRedis.getSsrcConfig());
  161 + }else {
  162 + mediaServerItemInDataBase.setSsrcConfig(
  163 + new SsrcConfig(
  164 + mediaServerItemInDataBase.getId(),
  165 + null,
  166 + sipConfig.getSipDomain()
  167 + )
  168 + );
105 169 }
106   - List<IMediaServerItem> result = new ArrayList<>();
107   - for (String id : zlmServers.keySet()) {
108   - IMediaServerItem mediaServerItem = zlmServers.get(id);
109   - mediaServerItem.setCount(zlmServerStatus.get(id) == null ? 0 : zlmServerStatus.get(id));
110   - result.add(mediaServerItem);
  170 + String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerItemInDataBase.getId();
  171 + redisUtil.set(key, mediaServerItemInDataBase);
  172 + }
  173 +
  174 + @Override
  175 + public List<MediaServerItem> getAll() {
  176 + List<MediaServerItem> result = new ArrayList<>();
  177 + List<Object> mediaServerKeys = redisUtil.scan(String.format("%S*", VideoManagerConstants.MEDIA_SERVER_PREFIX));
  178 + for (int i = 0; i < mediaServerKeys.size(); i++) {
  179 + String key = (String) mediaServerKeys.get(i);
  180 + result.add((MediaServerItem)redisUtil.get(key));
111 181 }
112 182 return result;
  183 + }
113 184  
114   -
115   -// return mediaServerMapper.queryAll();
  185 + @Override
  186 + public List<MediaServerItem> getAllOnline() {
  187 + String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX;
  188 + Set<String> mediaServerIdSet = redisUtil.zRevRange(key, 0, -1);
  189 + List<MediaServerItem> result = new ArrayList<>();
  190 + if (mediaServerIdSet != null && mediaServerIdSet.size() > 0) {
  191 + for (String mediaServerId : mediaServerIdSet) {
  192 + String serverKey = VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerId;
  193 + result.add((MediaServerItem) redisUtil.get(serverKey));
  194 + }
  195 + }
  196 + return result;
116 197 }
117 198  
118 199 /**
... ... @@ -121,26 +202,28 @@ public class MediaServerServiceImpl implements IMediaServerService {
121 202 * @return MediaServerItem
122 203 */
123 204 @Override
124   - public IMediaServerItem getOne(String mediaServerId) {
125   - if (mediaServerId ==null) return null;
126   - IMediaServerItem mediaServerItem = zlmServers.get(mediaServerId);
127   - if (mediaServerItem != null) {
128   - mediaServerItem.setCount(zlmServerStatus.get(mediaServerId) == null ? 0 : zlmServerStatus.get(mediaServerId));
129   - return mediaServerItem;
130   - }else {
131   - IMediaServerItem item = mediaServerMapper.queryOne(mediaServerId);
132   - if (item != null) {
133   - zlmServers.put(item.getId(), item);
134   - }
135   - return item;
136   - }
  205 + public MediaServerItem getOne(String mediaServerId) {
  206 + if (mediaServerId == null) return null;
  207 + String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerId;
  208 + return (MediaServerItem)redisUtil.get(key);
137 209 }
138 210  
139 211 @Override
140   - public IMediaServerItem getOneByHostAndPort(String host, int port) {
  212 + public MediaServerItem getOneByHostAndPort(String host, int port) {
141 213 return mediaServerMapper.queryOneByHostAndPort(host, port);
142 214 }
143 215  
  216 + @Override
  217 + public void clearMediaServerForOnline() {
  218 + String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX;
  219 + redisUtil.del(key);
  220 + }
  221 +
  222 + @Override
  223 + public void add(MediaServerItem mediaSerItem) {
  224 + mediaServerMapper.add(mediaSerItem);
  225 + }
  226 +
144 227 /**
145 228 * 处理zlm上线
146 229 * @param zlmServerConfig zlm上线携带的参数
... ... @@ -150,111 +233,100 @@ public class MediaServerServiceImpl implements IMediaServerService {
150 233 logger.info("[ {} ]-[ {}:{} ]已连接",
151 234 zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort());
152 235  
153   - IMediaServerItem serverItem = getOne(zlmServerConfig.getGeneralMediaServerId());
154   - String now = this.format.format(new Date(System.currentTimeMillis()));
155   - if (serverItem != null) {
156   - serverItem.setSecret(zlmServerConfig.getApiSecret());
157   - serverItem.setIp(zlmServerConfig.getIp());
  236 + MediaServerItem serverItem = mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId());
  237 + if (serverItem == null) {
  238 + serverItem = mediaServerMapper.queryOneByHostAndPort(zlmServerConfig.getIp(), zlmServerConfig.getHttpPort());
  239 + }
  240 + if (zlmServerConfig.getGeneralMediaServerId().equals(mediaConfig.getId())
  241 + || (zlmServerConfig.getIp().equals(mediaConfig.getIp()) && zlmServerConfig.getHttpPort() == mediaConfig.getHttpPort())) {
  242 + // 配置文件的zlm
158 243 // 如果是配置文件中的zlm。 也就是默认zlm。 一切以配置文件内容为准
159   - // docker部署不会使用zlm配置的端口号;
160   - // 直接编译部署的使用配置文件的端口号,如果zlm修改配改了配置,wvp自动修改
161   -
162   - if (serverItem.getId().equals(mediaConfig.getId())
163   - || (serverItem.getIp().equals(mediaConfig.getIp()) && serverItem.getHttpPort() == mediaConfig.getHttpPort())) {
164   - // 配置文件的zlm
165   - mediaConfig.setId(zlmServerConfig.getGeneralMediaServerId());
166   - mediaConfig.setUpdateTime(now);
167   - if (mediaConfig.getHttpPort() == 0) mediaConfig.setHttpPort(zlmServerConfig.getHttpPort());
168   - if (mediaConfig.getHttpSSlPort() == 0) mediaConfig.setHttpSSlPort(zlmServerConfig.getHttpSSLport());
169   - if (mediaConfig.getRtmpPort() == 0) mediaConfig.setRtmpPort(zlmServerConfig.getRtmpPort());
170   - if (mediaConfig.getRtmpSSlPort() == 0) mediaConfig.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort());
171   - if (mediaConfig.getRtspPort() == 0) mediaConfig.setRtspPort(zlmServerConfig.getRtspPort());
172   - if (mediaConfig.getRtspSSLPort() == 0) mediaConfig.setRtspSSLPort(zlmServerConfig.getRtspSSlport());
173   - if (mediaConfig.getRtpProxyPort() == 0) mediaConfig.setRtpProxyPort(zlmServerConfig.getRtpProxyPort());
174   - mediaServerMapper.update(mediaConfig);
175   - serverItem = mediaConfig.getMediaSerItem();
176   - setZLMConfig(mediaConfig);
177   - }else {
178   - if (!serverItem.isDocker()) {
179   - serverItem.setHttpPort(zlmServerConfig.getHttpPort());
180   - serverItem.setHttpSSlPort(zlmServerConfig.getHttpSSLport());
181   - serverItem.setRtmpPort(zlmServerConfig.getRtmpPort());
182   - serverItem.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort());
183   - serverItem.setRtpProxyPort(zlmServerConfig.getRtpProxyPort());
184   - serverItem.setRtspPort(zlmServerConfig.getRtspPort());
185   -
  244 + // docker部署不会使用zlm配置的端口号不是默认的则不做更新, 配置修改需要自行修改server配置;
  245 + MediaServerItem serverItemFromConfig = mediaConfig.getMediaSerItem();
  246 + serverItemFromConfig.setId(zlmServerConfig.getGeneralMediaServerId());
  247 + if (mediaConfig.getHttpPort() == 0) serverItemFromConfig.setHttpPort(zlmServerConfig.getHttpPort());
  248 + if (mediaConfig.getHttpSSlPort() == 0) serverItemFromConfig.setHttpSSlPort(zlmServerConfig.getHttpSSLport());
  249 + if (mediaConfig.getRtmpPort() == 0) serverItemFromConfig.setRtmpPort(zlmServerConfig.getRtmpPort());
  250 + if (mediaConfig.getRtmpSSlPort() == 0) serverItemFromConfig.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort());
  251 + if (mediaConfig.getRtspPort() == 0) serverItemFromConfig.setRtspPort(zlmServerConfig.getRtspPort());
  252 + if (mediaConfig.getRtspSSLPort() == 0) serverItemFromConfig.setRtspSSLPort(zlmServerConfig.getRtspSSlport());
  253 + if (mediaConfig.getRtpProxyPort() == 0) serverItemFromConfig.setRtpProxyPort(zlmServerConfig.getRtpProxyPort());
  254 + if (serverItem != null){
  255 + // 可能是同一个zlm但id发生了变化
  256 + if (!serverItem.getId().equals(zlmServerConfig.getGeneralMediaServerId())) {
  257 + mediaServerMapper.delOne(serverItem.getId());
  258 + redisUtil.del(VideoManagerConstants.MEDIA_SERVER_PREFIX + serverItem.getId());
  259 +
  260 + String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + serverItemFromConfig.getId();
  261 + serverItemFromConfig.setSsrcConfig(new SsrcConfig(serverItemFromConfig.getId(), null, sipConfig.getSipDomain()));
  262 + redisUtil.set(key, serverItemFromConfig);
  263 + mediaServerMapper.add(serverItemFromConfig);
  264 + }else {
  265 + mediaServerMapper.update(serverItemFromConfig);
186 266 }
187   - serverItem.setUpdateTime(now);
188   - mediaServerMapper.update(serverItem);
189   - setZLMConfig(serverItem);
  267 + }else {
  268 + String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + serverItemFromConfig.getId();
  269 + serverItemFromConfig.setSsrcConfig(new SsrcConfig(serverItemFromConfig.getId(), null, sipConfig.getSipDomain()));
  270 + redisUtil.set(key, serverItemFromConfig);
  271 + mediaServerMapper.add(serverItemFromConfig);
190 272 }
  273 + resetOnlineServerItem(serverItemFromConfig);
  274 + setZLMConfig(serverItemFromConfig);
191 275 }else {
192   - if (zlmServerConfig.getGeneralMediaServerId().equals(mediaConfig.getId())
193   - || (zlmServerConfig.getIp().equals(mediaConfig.getIp()) && zlmServerConfig.getHttpPort() == mediaConfig.getHttpPort())) {
194   - mediaConfig.setId(zlmServerConfig.getGeneralMediaServerId());
195   - mediaConfig.setCreateTime(now);
196   - mediaConfig.setUpdateTime(now);
197   - serverItem = mediaConfig.getMediaSerItem();
198   - mediaServerMapper.add(mediaConfig);
199   - }else {
200   - // 一个新的zlm接入wvp
201   - serverItem = new MediaServerItem(zlmServerConfig, sipIp);
202   - serverItem.setCreateTime(now);
203   - serverItem.setUpdateTime(now);
  276 + String now = this.format.format(new Date(System.currentTimeMillis()));
  277 + if (serverItem == null){
  278 + // 一个新的zlm接入wvp
  279 + serverItem = new MediaServerItem(zlmServerConfig, sipConfig.getSipIp());
  280 + serverItem.setCreateTime(now);
  281 + serverItem.setUpdateTime(now);
  282 + String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + serverItem.getId();
  283 + serverItem.setSsrcConfig(new SsrcConfig(serverItem.getId(), null, sipConfig.getSipDomain()));
  284 + redisUtil.set(key, serverItem);
  285 + // 存入数据库
204 286 mediaServerMapper.add(serverItem);
  287 + setZLMConfig(serverItem);
205 288 }
  289 + resetOnlineServerItem(serverItem);
206 290 }
207   - // 更新缓存
208   - if (zlmServerStatus.get(serverItem.getId()) == null) {
209   - zlmServers.put(serverItem.getId(), serverItem);
210   - zlmServerStatus.put(serverItem.getId(),0);
211   - }
212   - // 查询服务流数量
213   - IMediaServerItem finalServerItem = serverItem;
214   - zlmresTfulUtils.getMediaList(serverItem, null, null, "rtmp",(mediaList ->{
215   - Integer code = mediaList.getInteger("code");
216   - if (code == 0) {
217   - JSONArray data = mediaList.getJSONArray("data");
218   - if (data != null) {
219   - zlmServerStatus.put(finalServerItem.getId(),data.size());
220   - }else {
221   - zlmServerStatus.put(finalServerItem.getId(),0);
222   - }
223   -
224   - }
225   - }));
226   -
227 291 }
228 292  
229   - /**
230   - * 更新缓存
231   - * @param mediaServerItem zlm服务
232   - * @param count 在线数
233   - * @param online 在线状态
234   - */
235 293 @Override
236   - public void updateServerCatch(IMediaServerItem mediaServerItem, Integer count, Boolean online) {
237   - if (mediaServerItem != null) {
238   - zlmServers.put(mediaServerItem.getId(), mediaServerItem);
239   - Collection<Integer> values = zlmServerStatus.values();
240   - if (online != null && count != null) {
241   - zlmServerStatus.put(mediaServerItem.getId(), count);
242   - }
  294 + public void resetOnlineServerItem(MediaServerItem serverItem) {
  295 + // 更新缓存
  296 + String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX;
  297 + // 使用zset的分数作为当前并发量, 默认值设置为0
  298 + if (redisUtil.zScore(key, serverItem.getId()) == null) { // 不存在则设置默认值 已存在则重置
  299 + redisUtil.zAdd(key, serverItem.getId(), 0L);
  300 + // 查询服务流数量
  301 + zlmresTfulUtils.getMediaList(serverItem, null, null, "rtmp",(mediaList ->{
  302 + Integer code = mediaList.getInteger("code");
  303 + if (code == 0) {
  304 + JSONArray data = mediaList.getJSONArray("data");
  305 + if (data != null) {
  306 + redisUtil.zAdd(key, serverItem.getId(), data.size());
  307 + }
  308 + }
  309 + }));
  310 + }else {
  311 + clearRTPServer(serverItem);
243 312 }
  313 +
244 314 }
245 315  
  316 +
246 317 @Override
247 318 public void addCount(String mediaServerId) {
248   - if (zlmServerStatus.get(mediaServerId) != null) {
249   - zlmServerStatus.put(mediaServerId, zlmServerStatus.get(mediaServerId) + 1);
250   - }
  319 + if (mediaServerId == null) return;
  320 + String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX;
  321 + Double aDouble = redisUtil.zScore(key, mediaServerId);
  322 + redisUtil.zIncrScore(key, mediaServerId, 1);
  323 +
251 324 }
252 325  
253 326 @Override
254 327 public void removeCount(String mediaServerId) {
255   - if (zlmServerStatus.get(mediaServerId) != null) {
256   - zlmServerStatus.put(mediaServerId, zlmServerStatus.get(mediaServerId) - 1);
257   - }
  328 + String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX;
  329 + redisUtil.zIncrScore(key, mediaServerId, - 1);
258 330 }
259 331  
260 332 /**
... ... @@ -262,35 +334,18 @@ public class MediaServerServiceImpl implements IMediaServerService {
262 334 * @return MediaServerItem
263 335 */
264 336 @Override
265   - public IMediaServerItem getMediaServerForMinimumLoad() {
266   - int mediaCount = -1;
267   - String key = null;
268   - System.out.println(JSON.toJSONString(zlmServerStatus));
269   - if (zlmServerStatus.size() == 1) {
270   - Map.Entry entry = zlmServerStatus.entrySet().iterator().next();
271   - key= (String) entry.getKey();
272   - }else {
273   - for (String id : zlmServerStatus.keySet()) {
274   - if (key == null) {
275   - key = id;
276   - mediaCount = zlmServerStatus.get(id);
277   - }
278   - if (zlmServerStatus.get(id) == 0) {
279   - key = id;
280   - break;
281   - }else if (mediaCount >= zlmServerStatus.get(id)){
282   - mediaCount = zlmServerStatus.get(id);
283   - key = id;
284   - }
285   - }
286   - }
  337 + public MediaServerItem getMediaServerForMinimumLoad() {
  338 + String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX;
287 339  
288   - if (key == null) {
  340 + if (redisUtil.zSize(key) == null || redisUtil.zSize(key) == 0) {
289 341 logger.info("获取负载最低的节点时无在线节点");
290   - return null;
291   - }else{
292   - return zlmServers.get(key);
293 342 }
  343 +
  344 + // 获取分数最低的,及并发最低的
  345 + Set<Object> objects = redisUtil.ZRange(key, 0, -1);
  346 + ArrayList<Object> MediaServerObjectS = new ArrayList<>(objects);
  347 + String mediaServerId = (String)MediaServerObjectS.get(0);
  348 + return getOne(mediaServerId);
294 349 }
295 350  
296 351 /**
... ... @@ -298,7 +353,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
298 353 * @param mediaServerItem 服务ID
299 354 */
300 355 @Override
301   - public void setZLMConfig(IMediaServerItem mediaServerItem) {
  356 + public void setZLMConfig(MediaServerItem mediaServerItem) {
302 357 logger.info("[ {} ]-[ {}:{} ]设置zlm",
303 358 mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
304 359 String protocol = sslEnabled ? "https" : "http";
... ... @@ -333,8 +388,10 @@ public class MediaServerServiceImpl implements IMediaServerService {
333 388 logger.info("[ {} ]-[ {}:{} ]设置zlm成功",
334 389 mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
335 390 }else {
336   - logger.info("[ {} ]-[ {}:{} ]设置zlm失败" + responseJSON.getString("msg"),
  391 + logger.info("[ {} ]-[ {}:{} ]设置zlm失败",
337 392 mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
338 393 }
339 394 }
  395 +
  396 +
340 397 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
... ... @@ -4,9 +4,7 @@ import com.alibaba.fastjson.JSON;
4 4 import com.alibaba.fastjson.JSONArray;
5 5 import com.alibaba.fastjson.JSONObject;
6 6 import com.genersoft.iot.vmp.common.StreamInfo;
7   -import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
8 7 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
9   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
10 8 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
11 9 import com.genersoft.iot.vmp.service.IMediaServerService;
12 10 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
... ... @@ -33,14 +31,14 @@ public class MediaServiceImpl implements IMediaService {
33 31  
34 32  
35 33 @Override
36   - public StreamInfo getStreamInfoByAppAndStream(IMediaServerItem mediaInfo, String app, String stream, JSONArray tracks) {
  34 + public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, JSONArray tracks) {
37 35 return getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, null);
38 36 }
39 37  
40 38 @Override
41 39 public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, String addr) {
42 40 StreamInfo streamInfo = null;
43   - IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
  41 + MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
44 42 if (mediaInfo == null) {
45 43 return streamInfo;
46 44 }
... ... @@ -63,7 +61,7 @@ public class MediaServiceImpl implements IMediaService {
63 61 }
64 62  
65 63 @Override
66   - public StreamInfo getStreamInfoByAppAndStream(IMediaServerItem mediaInfo, String app, String stream, JSONArray tracks, String addr) {
  64 + public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, JSONArray tracks, String addr) {
67 65 StreamInfo streamInfoResult = new StreamInfo();
68 66 streamInfoResult.setStreamId(stream);
69 67 streamInfoResult.setApp(app);
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
... ... @@ -14,11 +14,12 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
14 14 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
15 15 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
16 16 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
17   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
18 17 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
19 18 import com.genersoft.iot.vmp.service.IMediaServerService;
  19 +import com.genersoft.iot.vmp.service.bean.SSRCInfo;
20 20 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
21 21 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  22 +import com.genersoft.iot.vmp.utils.redis.RedisUtil;
22 23 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
23 24 import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
24 25 import com.genersoft.iot.vmp.service.IMediaService;
... ... @@ -54,6 +55,9 @@ public class PlayServiceImpl implements IPlayService {
54 55 private IRedisCatchStorage redisCatchStorage;
55 56  
56 57 @Autowired
  58 + private RedisUtil redis;
  59 +
  60 + @Autowired
57 61 private DeferredResultHolder resultHolder;
58 62  
59 63 @Autowired
... ... @@ -73,7 +77,7 @@ public class PlayServiceImpl implements IPlayService {
73 77  
74 78  
75 79 @Override
76   - public PlayResult play(IMediaServerItem mediaServerItem, String deviceId, String channelId, ZLMHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent) {
  80 + public PlayResult play(MediaServerItem mediaServerItem, String deviceId, String channelId, ZLMHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent) {
77 81 PlayResult playResult = new PlayResult();
78 82 if (mediaServerItem == null) {
79 83 RequestMessage msg = new RequestMessage();
... ... @@ -97,14 +101,21 @@ public class PlayServiceImpl implements IPlayService {
97 101 // 超时处理
98 102 result.onTimeout(()->{
99 103 logger.warn(String.format("设备点播超时,deviceId:%s ,channelId:%s", deviceId, channelId));
100   - // 释放rtpserver
101   - mediaServerService.closeRTPServer(playResult.getDevice(), channelId);
102 104 RequestMessage msg = new RequestMessage();
103 105 msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + playResult.getUuid());
104 106 WVPResult wvpResult = new WVPResult();
105 107 wvpResult.setCode(-1);
106   - wvpResult.setMsg("Timeout");
  108 + SIPDialog dialog = streamSession.getDialog(deviceId, channelId);
  109 + if (dialog != null) {
  110 + wvpResult.setMsg("收流超时,请稍候重试");
  111 + }else {
  112 + wvpResult.setMsg("点播超时,请稍候重试");
  113 + }
107 114 msg.setData(wvpResult);
  115 + // 点播超时回复BYE
  116 + cmder.streamByeCmd(device.getDeviceId(), channelId);
  117 + // 释放rtpserver
  118 + mediaServerService.closeRTPServer(playResult.getDevice(), channelId);
108 119 resultHolder.invokeResult(msg);
109 120 });
110 121 result.onCompletion(()->{
... ... @@ -131,7 +142,7 @@ public class PlayServiceImpl implements IPlayService {
131 142 WVPResult wvpResult = (WVPResult)responseEntity.getBody();
132 143 if (wvpResult.getCode() == 0) {
133 144 StreamInfo streamInfoForSuccess = (StreamInfo)wvpResult.getData();
134   - IMediaServerItem mediaInfo = mediaServerService.getOne(streamInfoForSuccess.getMediaServerId());
  145 + MediaServerItem mediaInfo = mediaServerService.getOne(streamInfoForSuccess.getMediaServerId());
135 146 String streamUrl = streamInfoForSuccess.getFmp4();
136 147 // 请求截图
137 148 zlmresTfulUtils.getSnap(mediaInfo, streamUrl, 15, 1, path, fileName);
... ... @@ -142,14 +153,23 @@ public class PlayServiceImpl implements IPlayService {
142 153 }
143 154 });
144 155 if (streamInfo == null) {
  156 + SSRCInfo ssrcInfo;
  157 + String streamId = null;
  158 + if (mediaServerItem.isRtpEnable()) {
  159 + streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
  160 + }
  161 +
  162 + ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId);
  163 +
145 164 // 发送点播消息
146   - cmder.playStreamCmd(mediaServerItem, device, channelId, (IMediaServerItem mediaServerItemInUse, JSONObject response) -> {
  165 + cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInUse, JSONObject response) -> {
147 166 logger.info("收到订阅消息: " + response.toJSONString());
148 167 onPublishHandlerForPlay(mediaServerItemInUse, response, deviceId, channelId, uuid.toString());
149 168 if (hookEvent != null) {
150 169 hookEvent.response(mediaServerItem, response);
151 170 }
152 171 }, (event) -> {
  172 + // 点播返回sip错误
153 173 RequestMessage msg = new RequestMessage();
154 174 msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
155 175 Response response = event.getResponse();
... ... @@ -162,6 +182,7 @@ public class PlayServiceImpl implements IPlayService {
162 182 if (errorEvent != null) {
163 183 errorEvent.response(event);
164 184 }
  185 +
165 186 });
166 187 } else {
167 188 String streamId = streamInfo.getStreamId();
... ... @@ -176,7 +197,7 @@ public class PlayServiceImpl implements IPlayService {
176 197 return playResult;
177 198 }
178 199 String mediaServerId = streamInfo.getMediaServerId();
179   - IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
  200 + MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
180 201  
181 202 JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId);
182 203 if (rtpInfo != null && rtpInfo.getBoolean("exist")) {
... ... @@ -194,9 +215,17 @@ public class PlayServiceImpl implements IPlayService {
194 215 hookEvent.response(mediaServerItem, JSONObject.parseObject(JSON.toJSONString(streamInfo)));
195 216 }
196 217 } else {
  218 + // TODO 点播前是否重置状态
197 219 redisCatchStorage.stopPlay(streamInfo);
198 220 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
199   - cmder.playStreamCmd(mediaServerItem, device, channelId, (IMediaServerItem mediaServerItemInuse, JSONObject response) -> {
  221 + SSRCInfo ssrcInfo;
  222 + String streamId2 = null;
  223 + if (mediaServerItem.isRtpEnable()) {
  224 + streamId2 = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
  225 + }
  226 + ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId2);
  227 +
  228 + cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> {
200 229 logger.info("收到订阅消息: " + response.toJSONString());
201 230 onPublishHandlerForPlay(mediaServerItemInuse, response, deviceId, channelId, uuid.toString());
202 231 }, (event) -> {
... ... @@ -218,7 +247,7 @@ public class PlayServiceImpl implements IPlayService {
218 247 }
219 248  
220 249 @Override
221   - public void onPublishHandlerForPlay(IMediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) {
  250 + public void onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) {
222 251 RequestMessage msg = new RequestMessage();
223 252 msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
224 253 StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid);
... ... @@ -228,14 +257,6 @@ public class PlayServiceImpl implements IPlayService {
228 257 deviceChannel.setStreamId(streamInfo.getStreamId());
229 258 storager.startPlay(deviceId, channelId, streamInfo.getStreamId());
230 259 }
231   - ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId);
232   - SIPDialog dialog = (SIPDialog)transaction.getDialog();
233   - StreamInfo.TransactionInfo transactionInfo = new StreamInfo.TransactionInfo();
234   - transactionInfo.callId = dialog.getCallId().getCallId();
235   - transactionInfo.localTag = dialog.getLocalTag();
236   - transactionInfo.remoteTag = dialog.getRemoteTag();
237   - transactionInfo.branch = dialog.getFirstTransactionInt().getBranchId();
238   - streamInfo.setTransactionInfo(transactionInfo);
239 260 redisCatchStorage.startPlay(streamInfo);
240 261 msg.setData(JSON.toJSONString(streamInfo));
241 262  
... ... @@ -254,10 +275,10 @@ public class PlayServiceImpl implements IPlayService {
254 275 }
255 276  
256 277 @Override
257   - public IMediaServerItem getNewMediaServerItem(Device device) {
  278 + public MediaServerItem getNewMediaServerItem(Device device) {
258 279 if (device == null) return null;
259 280 String mediaServerId = device.getMediaServerId();
260   - IMediaServerItem mediaServerItem = null;
  281 + MediaServerItem mediaServerItem = null;
261 282 if (mediaServerId == null) {
262 283 mediaServerItem = mediaServerService.getMediaServerForMinimumLoad();
263 284 }else {
... ... @@ -270,7 +291,7 @@ public class PlayServiceImpl implements IPlayService {
270 291 }
271 292  
272 293 @Override
273   - public void onPublishHandlerForPlayBack(IMediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) {
  294 + public void onPublishHandlerForPlayBack(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) {
274 295 RequestMessage msg = new RequestMessage();
275 296 msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
276 297 StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid);
... ... @@ -285,7 +306,7 @@ public class PlayServiceImpl implements IPlayService {
285 306 }
286 307 }
287 308  
288   - public StreamInfo onPublishHandler(IMediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) {
  309 + public StreamInfo onPublishHandler(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) {
289 310 String streamId = resonse.getString("stream");
290 311 JSONArray tracks = resonse.getJSONArray("tracks");
291 312 StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem,"rtp", streamId, tracks);
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
... ... @@ -3,7 +3,6 @@ package com.genersoft.iot.vmp.service.impl;
3 3 import com.alibaba.fastjson.JSONObject;
4 4 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
5 5 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
6   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
7 6 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
8 7 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
9 8 import com.genersoft.iot.vmp.service.IGbStreamService;
... ... @@ -58,7 +57,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
58 57  
59 58 @Override
60 59 public String save(StreamProxyItem param) {
61   - IMediaServerItem mediaInfo;
  60 + MediaServerItem mediaInfo;
62 61 if ("auto".equals(param.getMediaServerId())){
63 62 mediaInfo = mediaServerService.getMediaServerForMinimumLoad();
64 63 }else {
... ... @@ -120,7 +119,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
120 119 @Override
121 120 public JSONObject addStreamProxyToZlm(StreamProxyItem param) {
122 121 JSONObject result = null;
123   - IMediaServerItem mediaServerItem = null;
  122 + MediaServerItem mediaServerItem = null;
124 123 if (param.getMediaServerId() == null) {
125 124 logger.warn("添加代理时MediaServerId 为null");
126 125 return null;
... ... @@ -141,7 +140,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
141 140 @Override
142 141 public JSONObject removeStreamProxyFromZlm(StreamProxyItem param) {
143 142 if (param ==null) return null;
144   - IMediaServerItem mediaServerItem = mediaServerService.getOne(param.getMediaServerId());
  143 + MediaServerItem mediaServerItem = mediaServerService.getOne(param.getMediaServerId());
145 144 JSONObject result = zlmresTfulUtils.closeStreams(mediaServerItem, param.getApp(), param.getStream());
146 145 return result;
147 146 }
... ... @@ -198,7 +197,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
198 197 }
199 198  
200 199 @Override
201   - public JSONObject getFFmpegCMDs(IMediaServerItem mediaServerItem) {
  200 + public JSONObject getFFmpegCMDs(MediaServerItem mediaServerItem) {
202 201 JSONObject result = new JSONObject();
203 202 JSONObject mediaServerConfigResuly = zlmresTfulUtils.getMediaServerConfig(mediaServerItem);
204 203 if (mediaServerConfigResuly != null && mediaServerConfigResuly.getInteger("code") == 0
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java
... ... @@ -5,7 +5,6 @@ import com.alibaba.fastjson.JSONObject;
5 5 import com.alibaba.fastjson.TypeReference;
6 6 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
7 7 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
8   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
9 8 import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
10 9 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
11 10 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
... ... @@ -43,7 +42,7 @@ public class StreamPushServiceImpl implements IStreamPushService {
43 42 private IMediaServerService mediaServerService;
44 43  
45 44 @Override
46   - public List<StreamPushItem> handleJSON(String jsonData, IMediaServerItem mediaServerItem) {
  45 + public List<StreamPushItem> handleJSON(String jsonData, MediaServerItem mediaServerItem) {
47 46 if (jsonData == null) return null;
48 47  
49 48 Map<String, StreamPushItem> result = new HashMap<>();
... ... @@ -98,7 +97,7 @@ public class StreamPushServiceImpl implements IStreamPushService {
98 97 @Override
99 98 public boolean removeFromGB(GbStream stream) {
100 99 int del = gbStreamMapper.del(stream.getApp(), stream.getStream());
101   - IMediaServerItem mediaInfo = mediaServerService.getOne(stream.getMediaServerId());
  100 + MediaServerItem mediaInfo = mediaServerService.getOne(stream.getMediaServerId());
102 101 JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaInfo, stream.getApp(), stream.getStream());
103 102 if (mediaList == null) {
104 103 streamPushMapper.del(stream.getApp(), stream.getStream());
... ...
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
... ... @@ -5,8 +5,6 @@ import com.genersoft.iot.vmp.common.StreamInfo;
5 5 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
6 6 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
7 7 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
8   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
9   -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
10 8  
11 9 import java.util.List;
12 10 import java.util.Map;
... ...
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java
... ... @@ -3,7 +3,6 @@ package com.genersoft.iot.vmp.storager;
3 3 import java.util.List;
4 4  
5 5 import com.genersoft.iot.vmp.gb28181.bean.*;
6   -import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
7 6 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
8 7 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
9 8 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
... ...
src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java
1 1 package com.genersoft.iot.vmp.storager.dao;
2 2  
3   -import com.genersoft.iot.vmp.conf.MediaConfig;
4   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
5 3 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
6 4 import org.apache.ibatis.annotations.Insert;
7 5 import org.apache.ibatis.annotations.Mapper;
... ... @@ -35,6 +33,7 @@ public interface MediaServerMapper {
35 33 "rtpEnable, " +
36 34 "rtpPortRange, " +
37 35 "recordAssistPort, " +
  36 + "defaultServer, " +
38 37 "createTime, " +
39 38 "updateTime" +
40 39 ") VALUES " +
... ... @@ -57,9 +56,10 @@ public interface MediaServerMapper {
57 56 "${rtpEnable}, " +
58 57 "'${rtpPortRange}', " +
59 58 "${recordAssistPort}, " +
  59 + "${defaultServer}, " +
60 60 "'${createTime}', " +
61 61 "'${updateTime}')")
62   - int add(IMediaServerItem mediaServerItem);
  62 + int add(MediaServerItem mediaServerItem);
63 63  
64 64 @Update(value = {" <script>" +
65 65 "UPDATE media_server " +
... ... @@ -83,7 +83,7 @@ public interface MediaServerMapper {
83 83 "<if test=\"recordAssistPort != null\">, recordAssistPort=${recordAssistPort}</if>" +
84 84 "WHERE id='${id}'"+
85 85 " </script>"})
86   - int update(IMediaServerItem mediaServerItem);
  86 + int update(MediaServerItem mediaServerItem);
87 87  
88 88 @Select("SELECT * FROM media_server WHERE id='${id}'")
89 89 MediaServerItem queryOne(String id);
... ... @@ -92,7 +92,7 @@ public interface MediaServerMapper {
92 92 List<MediaServerItem> queryAll();
93 93  
94 94 @Select("DELETE FROM media_server WHERE id='${id}'")
95   - int delOne(String secret);
  95 + void delOne(String id);
96 96  
97 97 @Select("SELECT * FROM media_server WHERE ip='${host}' and httpPort=${port}")
98 98 MediaServerItem queryOneByHostAndPort(String host, int port);
... ...
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
... ... @@ -3,10 +3,7 @@ package com.genersoft.iot.vmp.storager.impl;
3 3 import com.alibaba.fastjson.JSONObject;
4 4 import com.genersoft.iot.vmp.common.StreamInfo;
5 5 import com.genersoft.iot.vmp.common.VideoManagerConstants;
6   -import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
7 6 import com.genersoft.iot.vmp.gb28181.bean.*;
8   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
9   -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
10 7 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
11 8 import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
12 9 import com.genersoft.iot.vmp.utils.redis.RedisUtil;
... ...
src/main/java/com/genersoft/iot/vmp/utils/ConfigConst.java 0 → 100644
  1 +package com.genersoft.iot.vmp.utils;
  2 +
  3 +public class ConfigConst {
  4 + /**
  5 + * 播流最大并发个数
  6 + */
  7 + public static final Integer MAX_STRTEAM_COUNT = 10000;
  8 +}
... ...
src/main/java/com/genersoft/iot/vmp/utils/SerializeUtils.java 0 → 100644
  1 +package com.genersoft.iot.vmp.utils;
  2 +
  3 +import java.io.*;
  4 +
  5 +public class SerializeUtils {
  6 + public static byte[] serialize(Object obj){
  7 + byte[] bytes = null;
  8 + try {
  9 + ByteArrayOutputStream baos=new ByteArrayOutputStream();;
  10 + ObjectOutputStream oos=new ObjectOutputStream(baos);
  11 + oos.writeObject(obj);
  12 + bytes=baos.toByteArray();
  13 + baos.close();
  14 + oos.close();
  15 + } catch (IOException e) {
  16 + e.printStackTrace();
  17 + }
  18 + return bytes;
  19 + }
  20 + public static Object deSerialize(byte[] bytes){
  21 + Object obj=null;
  22 + try {
  23 + ByteArrayInputStream bais=new ByteArrayInputStream(bytes);
  24 + ObjectInputStream ois=new ObjectInputStream(bais);
  25 + obj=ois.readObject();
  26 + } catch (Exception e) {
  27 + e.printStackTrace();
  28 + }
  29 + return obj;
  30 + }
  31 +}
... ...
src/main/java/com/genersoft/iot/vmp/utils/redis/JedisUtil.java 0 → 100644
  1 +package com.genersoft.iot.vmp.utils.redis;
  2 +
  3 +import org.springframework.beans.factory.annotation.Autowired;
  4 +import org.springframework.stereotype.Component;
  5 +import redis.clients.jedis.Jedis;
  6 +import redis.clients.jedis.JedisPool;
  7 +
  8 +import java.util.Set;
  9 +
  10 +/**
  11 + * @Description:Jedis工具类
  12 + * @author: wangshaopeng@sunnybs.com
  13 + * @date: 2021年03月22日 下午8:27:29
  14 + */
  15 +@Component
  16 +public class JedisUtil {
  17 +
  18 + @Autowired
  19 + private JedisPool jedisPool;
  20 +
  21 + // ============================== Key ==============================
  22 +
  23 + /**
  24 + * 检查给定 key 是否存在。
  25 + *
  26 + * @param key
  27 + * @return
  28 + */
  29 + public Boolean exists(String key) {
  30 + Jedis jedis = null;
  31 + try {
  32 + jedis = jedisPool.getResource();
  33 + Boolean exists = jedis.exists(key);
  34 + return exists;
  35 + } finally {
  36 + returnToPool(jedis);
  37 + }
  38 + }
  39 +
  40 +
  41 + // ============================== Set ==============================
  42 +
  43 + /**
  44 + * SADD key member [member ...]
  45 + * 将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略。
  46 + * 假如 key 不存在,则创建一个只包含 member 元素作成员的集合。
  47 + * 当 key 不是集合类型时,返回一个错误。
  48 + */
  49 + public Long sadd(String key, String... members) {
  50 + Jedis jedis = null;
  51 + try {
  52 + jedis = jedisPool.getResource();
  53 + Long smove = jedis.sadd(key, members);
  54 + return smove;
  55 + } finally {
  56 + returnToPool(jedis);
  57 + }
  58 + }
  59 +
  60 + /**
  61 + * SMEMBERS key
  62 + * 返回集合 key 中的所有成员。
  63 + * 不存在的 key 被视为空集合。
  64 + */
  65 + public Set<String> smembers(String key) {
  66 + Jedis jedis = null;
  67 + try {
  68 + jedis = jedisPool.getResource();
  69 + Set<String> smembers = jedis.smembers(key);
  70 + return smembers;
  71 + } finally {
  72 + returnToPool(jedis);
  73 + }
  74 + }
  75 +
  76 +
  77 + /**
  78 + * SREM key member1 [member2]
  79 + * 移除集合中一个或多个成员
  80 + */
  81 + public Long srem(String key, String... member) {
  82 + Jedis jedis = null;
  83 + try {
  84 + jedis = jedisPool.getResource();
  85 + Long srem = jedis.srem(key, member);
  86 + return srem;
  87 + } finally {
  88 + returnToPool(jedis);
  89 + }
  90 + }
  91 +
  92 + private void returnToPool(Jedis jedis) {
  93 + if (jedis != null) {
  94 + jedis.close();
  95 + }
  96 + }
  97 +}
0 98 \ No newline at end of file
... ...
src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java
... ... @@ -415,10 +415,10 @@ public class RedisUtil {
415 415 *
416 416 * @param key
417 417 * @param value
418   - * @param score
  418 + * @param delta -1 表示减 1 表示加1
419 419 */
420   - public Double zIncrScore(Object key, Object value, double score) {
421   - return redisTemplate.opsForZSet().incrementScore(key, value, score);
  420 + public Double zIncrScore(Object key, Object value, double delta) {
  421 + return redisTemplate.opsForZSet().incrementScore(key, value, delta);
422 422 }
423 423  
424 424 /**
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
... ... @@ -2,13 +2,12 @@ package com.genersoft.iot.vmp.vmanager.gb28181.play;
2 2  
3 3 import com.alibaba.fastjson.JSONArray;
4 4 import com.genersoft.iot.vmp.common.StreamInfo;
  5 +import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
5 6 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
6   -import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
7 7 import com.genersoft.iot.vmp.gb28181.bean.Device;
8 8 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
9 9 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
10 10 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
11   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
12 11 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
13 12 import com.genersoft.iot.vmp.service.IMediaServerService;
14 13 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
... ... @@ -37,7 +36,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
37 36 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
38 37 import org.springframework.web.context.request.async.DeferredResult;
39 38  
40   -import java.util.Enumeration;
  39 +import java.util.List;
41 40 import java.util.Map;
42 41 import java.util.UUID;
43 42  
... ... @@ -89,7 +88,7 @@ public class PlayController {
89 88  
90 89 // 获取可用的zlm
91 90 Device device = storager.queryVideoDevice(deviceId);
92   - IMediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
  91 + MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
93 92 PlayResult playResult = playService.play(newMediaServerItem, deviceId, channelId, null, null);
94 93  
95 94 return playResult.getResult();
... ... @@ -174,7 +173,7 @@ public class PlayController {
174 173 logger.warn("视频转码API调用失败!, 视频流已经停止!");
175 174 return new ResponseEntity<String>("未找到视频流信息, 视频流可能已经停止", HttpStatus.OK);
176 175 }
177   - IMediaServerItem mediaInfo = mediaServerService.getOne(streamInfo.getMediaServerId());
  176 + MediaServerItem mediaInfo = mediaServerService.getOne(streamInfo.getMediaServerId());
178 177 JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId);
179 178 if (!rtpInfo.getBoolean("exist")) {
180 179 logger.warn("视频转码API调用失败!, 视频流已停止推流!");
... ... @@ -219,7 +218,7 @@ public class PlayController {
219 218 result.put("msg", "mediaServerId is null");
220 219 return new ResponseEntity<String>( result.toJSONString(), HttpStatus.BAD_REQUEST);
221 220 }
222   - IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
  221 + MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
223 222 if (mediaInfo == null) {
224 223 result.put("code", 0);
225 224 result.put("msg", "使用的流媒体已经停止运行");
... ... @@ -307,16 +306,16 @@ public class PlayController {
307 306 logger.debug("获取所有的ssrc");
308 307 }
309 308 JSONArray objects = new JSONArray();
310   - for(Map.Entry<String, String> entry: streamSession.getSsrcMap().entrySet()) {
311   - System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
  309 + List<SsrcTransaction> allSsrc = streamSession.getAllSsrc();
  310 + for (SsrcTransaction transaction : allSsrc) {
312 311 JSONObject jsonObject = new JSONObject();
313   - String[] keyArray = entry.getKey().split("_");
314   - jsonObject.put("deviceId", keyArray[0]);
315   - jsonObject.put("channelId", keyArray[1]);
316   - jsonObject.put("ssrc", entry.getValue());
317   - jsonObject.put("streamId", streamSession.getStreamIdMap().get(entry.getKey()));
  312 + jsonObject.put("deviceId", transaction.getDeviceId());
  313 + jsonObject.put("channelId", transaction.getChannelId());
  314 + jsonObject.put("ssrc", transaction.getSsrc());
  315 + jsonObject.put("streamId", transaction.getStreamId());
318 316 objects.add(jsonObject);
319 317 }
  318 +
320 319 WVPResult<JSONObject> result = new WVPResult<>();
321 320 result.setCode(0);
322 321 result.setMsg("success");
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java
... ... @@ -3,9 +3,9 @@ package com.genersoft.iot.vmp.vmanager.gb28181.playback;
3 3 import com.genersoft.iot.vmp.common.StreamInfo;
4 4 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
5 5 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
6   -//import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
7   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
8 6 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
  7 +import com.genersoft.iot.vmp.service.IMediaServerService;
  8 +import com.genersoft.iot.vmp.service.bean.SSRCInfo;
9 9 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
10 10 import com.genersoft.iot.vmp.service.IPlayService;
11 11 import io.swagger.annotations.Api;
... ... @@ -58,6 +58,9 @@ public class DownloadController {
58 58 @Autowired
59 59 private DeferredResultHolder resultHolder;
60 60  
  61 + @Autowired
  62 + private IMediaServerService mediaServerService;
  63 +
61 64 @ApiOperation("开始历史媒体下载")
62 65 @ApiImplicitParams({
63 66 @ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class),
... ... @@ -90,7 +93,7 @@ public class DownloadController {
90 93 cmder.streamByeCmd(deviceId, channelId);
91 94 }
92 95 resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result);
93   - IMediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
  96 + MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
94 97 if (newMediaServerItem == null) {
95 98 logger.warn(String.format("设备下载响应超时,deviceId:%s ,channelId:%s", deviceId, channelId));
96 99 RequestMessage msg = new RequestMessage();
... ... @@ -99,7 +102,10 @@ public class DownloadController {
99 102 resultHolder.invokeResult(msg);
100 103 return result;
101 104 }
102   - cmder.downloadStreamCmd(newMediaServerItem, device, channelId, startTime, endTime, downloadSpeed, (IMediaServerItem mediaServerItem, JSONObject response) -> {
  105 +
  106 + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null);
  107 +
  108 + cmder.downloadStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, (MediaServerItem mediaServerItem, JSONObject response) -> {
103 109 logger.info("收到订阅消息: " + response.toJSONString());
104 110 playService.onPublishHandlerForPlayBack(mediaServerItem, response, deviceId, channelId, uuid.toString());
105 111 }, event -> {
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java
... ... @@ -4,8 +4,9 @@ import com.genersoft.iot.vmp.common.StreamInfo;
4 4 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
5 5 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
6 6 //import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
7   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
8 7 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
  8 +import com.genersoft.iot.vmp.service.IMediaServerService;
  9 +import com.genersoft.iot.vmp.service.bean.SSRCInfo;
9 10 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
10 11 import com.genersoft.iot.vmp.service.IPlayService;
11 12 import io.swagger.annotations.Api;
... ... @@ -58,6 +59,9 @@ public class PlaybackController {
58 59 @Autowired
59 60 private DeferredResultHolder resultHolder;
60 61  
  62 + @Autowired
  63 + private IMediaServerService mediaServerService;
  64 +
61 65 @ApiOperation("开始视频回放")
62 66 @ApiImplicitParams({
63 67 @ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class),
... ... @@ -74,6 +78,15 @@ public class PlaybackController {
74 78 }
75 79 UUID uuid = UUID.randomUUID();
76 80 DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(30000L);
  81 +
  82 + Device device = storager.queryVideoDevice(deviceId);
  83 + if (device == null) {
  84 + result.setResult(new ResponseEntity<>(HttpStatus.BAD_REQUEST));
  85 + return result;
  86 + }
  87 + MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
  88 + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null);
  89 +
77 90 // 超时处理
78 91 result.onTimeout(()->{
79 92 logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId));
... ... @@ -82,14 +95,14 @@ public class PlaybackController {
82 95 msg.setData("Timeout");
83 96 resultHolder.invokeResult(msg);
84 97 });
85   - Device device = storager.queryVideoDevice(deviceId);
  98 +
86 99 StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, channelId);
87 100 if (streamInfo != null) {
88 101 // 停止之前的回放
89 102 cmder.streamByeCmd(deviceId, channelId);
90 103 }
91 104 resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result);
92   - IMediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
  105 +
93 106 if (newMediaServerItem == null) {
94 107 logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId));
95 108 RequestMessage msg = new RequestMessage();
... ... @@ -98,7 +111,8 @@ public class PlaybackController {
98 111 resultHolder.invokeResult(msg);
99 112 return result;
100 113 }
101   - cmder.playbackStreamCmd(newMediaServerItem, device, channelId, startTime, endTime, (IMediaServerItem mediaServerItem, JSONObject response) -> {
  114 +
  115 + cmder.playbackStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, (MediaServerItem mediaServerItem, JSONObject response) -> {
102 116 logger.info("收到订阅消息: " + response.toJSONString());
103 117 playService.onPublishHandlerForPlayBack(mediaServerItem, response, deviceId, channelId, uuid.toString());
104 118 }, event -> {
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/session/PlayTypeEnum.java 0 → 100644
  1 +package com.genersoft.iot.vmp.vmanager.gb28181.session;
  2 +
  3 +public enum PlayTypeEnum {
  4 +
  5 + PLAY("0", "直播"),
  6 + PLAY_BACK("1", "回放");
  7 +
  8 + private String value;
  9 + private String name;
  10 +
  11 + PlayTypeEnum(String value, String name) {
  12 + this.value = value;
  13 + this.name = name;
  14 + }
  15 +
  16 + public String getValue() {
  17 + return value;
  18 + }
  19 +
  20 + public String getName() {
  21 + return name;
  22 + }
  23 +}
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java
1 1 package com.genersoft.iot.vmp.vmanager.server;
2 2  
3 3 import com.genersoft.iot.vmp.VManageBootstrap;
4   -import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
5   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
  4 +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
6 5 import com.genersoft.iot.vmp.service.IMediaServerService;
7   -import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
8 6 import com.genersoft.iot.vmp.utils.SpringBeanFactory;
9 7 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
10 8 import gov.nist.javax.sip.SipStackImpl;
... ... @@ -17,7 +15,6 @@ import org.springframework.web.bind.annotation.*;
17 15 import javax.sip.ListeningPoint;
18 16 import javax.sip.ObjectInUseException;
19 17 import javax.sip.SipProvider;
20   -import java.util.ArrayList;
21 18 import java.util.Iterator;
22 19 import java.util.List;
23 20  
... ... @@ -38,19 +35,30 @@ public class ServerController {
38 35 @ApiOperation("流媒体服务列表")
39 36 @GetMapping(value = "/media_server/list")
40 37 @ResponseBody
41   - public WVPResult<List<IMediaServerItem>> getMediaServerList(){
42   - WVPResult<List<IMediaServerItem>> result = new WVPResult<>();
  38 + public WVPResult<List<MediaServerItem>> getMediaServerList(){
  39 + WVPResult<List<MediaServerItem>> result = new WVPResult<>();
43 40 result.setCode(0);
44 41 result.setMsg("success");
45 42 result.setData(mediaServerService.getAll());
46 43 return result;
47 44 }
48 45  
  46 + @ApiOperation("在线流媒体服务列表")
  47 + @GetMapping(value = "/media_server/online/list")
  48 + @ResponseBody
  49 + public WVPResult<List<MediaServerItem>> getOnlineMediaServerList(){
  50 + WVPResult<List<MediaServerItem>> result = new WVPResult<>();
  51 + result.setCode(0);
  52 + result.setMsg("success");
  53 + result.setData(mediaServerService.getAllOnline());
  54 + return result;
  55 + }
  56 +
49 57 @ApiOperation("获取流媒体服务")
50 58 @GetMapping(value = "/media_server/one/{id}")
51 59 @ResponseBody
52   - public WVPResult<IMediaServerItem> getMediaServer(@PathVariable String id){
53   - WVPResult<IMediaServerItem> result = new WVPResult<>();
  60 + public WVPResult<MediaServerItem> getMediaServer(@PathVariable String id){
  61 + WVPResult<MediaServerItem> result = new WVPResult<>();
54 62 result.setCode(0);
55 63 result.setMsg("success");
56 64 result.setData(mediaServerService.getOne(id));
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java
1 1 package com.genersoft.iot.vmp.vmanager.streamProxy;
2 2  
3 3 import com.alibaba.fastjson.JSONObject;
4   -import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
5 4 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
6 5 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
7 6 import com.genersoft.iot.vmp.service.IMediaServerService;
... ... @@ -9,7 +8,6 @@ import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
9 8 import com.genersoft.iot.vmp.service.IStreamProxyService;
10 9 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
11 10 import com.github.pagehelper.PageInfo;
12   -import io.netty.util.internal.StringUtil;
13 11 import io.swagger.annotations.Api;
14 12 import io.swagger.annotations.ApiImplicitParam;
15 13 import io.swagger.annotations.ApiImplicitParams;
... ... @@ -86,7 +84,7 @@ public class StreamProxyController {
86 84 public WVPResult getFFmpegCMDs(@RequestParam String mediaServerId){
87 85 logger.debug("获取节点[ {} ]ffmpeg.cmd模板", mediaServerId );
88 86  
89   - IMediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
  87 + MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
90 88 JSONObject data = streamProxyService.getFFmpegCMDs(mediaServerItem);
91 89 WVPResult<JSONObject> result = new WVPResult<>();
92 90 result.setCode(0);
... ...
src/main/resources/all-application.yml
... ... @@ -17,6 +17,12 @@ spring:
17 17 password:
18 18 # [可选] 超时时间
19 19 timeout: 10000
  20 + # [可选] 一个pool最多可分配多少个jedis实例
  21 + poolMaxTotal: 1000
  22 + # [可选] 一个pool最多有多少个状态为idle(空闲)的jedis实例
  23 + poolMaxIdle: 500
  24 + # [可选] 最大的等待时间(秒)
  25 + poolMaxWait: 5
20 26 # [可选] jdbc数据库配置, 项目使用sqlite作为数据库,一般不需要配置
21 27 datasource:
22 28 # 使用mysql 打开23-28行注释, 删除29-36行
... ... @@ -124,6 +130,7 @@ logging:
124 130 level:
125 131 com.genersoft.iot: debug
126 132 com.genersoft.iot.vmp.storager.dao: info
  133 + com.genersoft.iot.vmp.gb28181: info
127 134 # [根据业务需求配置]
128 135 user-settings:
129 136 # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
... ...
src/main/resources/application-dev.yml
... ... @@ -76,6 +76,8 @@ logging:
76 76 level:
77 77 com.genersoft.iot: debug
78 78 com.genersoft.iot.vmp.storager.dao: info
  79 + com.genersoft.iot.vmp.gb28181: info
  80 +
79 81 # [根据业务需求配置]
80 82 user-settings:
81 83 # 推流直播是否录制
... ...
src/main/resources/wvp.sqlite
No preview for this file type
web_src/src/components/service/MediaServer.js
... ... @@ -9,7 +9,7 @@ class MediaServer{
9 9 getMediaServerList(callback){
10 10 this.$axios({
11 11 method: 'get',
12   - url:`/api/server/media_server/list`,
  12 + url:`/api/server/media_server/online/list`,
13 13 }).then(function (res) {
14 14 if (typeof (callback) == "function") callback(res.data)
15 15 }).catch(function (error) {
... ...