Browse Source

优化集群方案, 每个zlm一套ssrc;
优化集群下的docker接入逻辑;
更正sql脚本;
支持重启不设置设备离线。重启SIP事务不丢失

64850858 4 năm trước cách đây
mục cha
commit
3469271ec2
57 tập tin đã thay đổi với 1312 bổ sung1070 xóa
  1. 7 0
      pom.xml
  2. 107 97
      sql/mysql.sql
  3. 6 0
      src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
  4. 15 173
      src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java
  5. 10 10
      src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java
  6. 36 1
      src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java
  7. 0 31
      src/main/java/com/genersoft/iot/vmp/conf/SipDeviceRunner.java
  8. 13 15
      src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
  9. 70 0
      src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java
  10. 1 2
      src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java
  11. 140 0
      src/main/java/com/genersoft/iot/vmp/gb28181/session/SsrcConfig.java
  12. 0 101
      src/main/java/com/genersoft/iot/vmp/gb28181/session/SsrcUtil.java
  13. 80 31
      src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java
  14. 1 1
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java
  15. 4 6
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
  16. 89 122
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
  17. 1 2
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java
  18. 1 2
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java
  19. 1 4
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java
  20. 13 1
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/InviteResponseProcessor.java
  21. 14 10
      src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
  22. 5 3
      src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java
  23. 3 6
      src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java
  24. 21 24
      src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java
  25. 39 41
      src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
  26. 20 14
      src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java
  27. 0 92
      src/main/java/com/genersoft/iot/vmp/media/zlm/dto/IMediaServerItem.java
  28. 41 13
      src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java
  29. 20 10
      src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java
  30. 2 3
      src/main/java/com/genersoft/iot/vmp/service/IMediaService.java
  31. 4 5
      src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
  32. 1 2
      src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java
  33. 2 2
      src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java
  34. 38 0
      src/main/java/com/genersoft/iot/vmp/service/bean/SSRCInfo.java
  35. 221 164
      src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
  36. 3 5
      src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
  37. 43 22
      src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
  38. 4 5
      src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
  39. 2 3
      src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java
  40. 0 2
      src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
  41. 0 1
      src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java
  42. 5 5
      src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java
  43. 0 3
      src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
  44. 8 0
      src/main/java/com/genersoft/iot/vmp/utils/ConfigConst.java
  45. 31 0
      src/main/java/com/genersoft/iot/vmp/utils/SerializeUtils.java
  46. 97 0
      src/main/java/com/genersoft/iot/vmp/utils/redis/JedisUtil.java
  47. 3 3
      src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java
  48. 12 13
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
  49. 10 4
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java
  50. 18 4
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java
  51. 23 0
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/session/PlayTypeEnum.java
  52. 16 8
      src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java
  53. 1 3
      src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java
  54. 7 0
      src/main/resources/all-application.yml
  55. 2 0
      src/main/resources/application-dev.yml
  56. BIN
      src/main/resources/wvp.sqlite
  57. 1 1
      web_src/src/components/service/MediaServer.js

+ 7 - 0
pom.xml

@@ -46,6 +46,7 @@
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 		<maven.build.timestamp.format>MMddHHmm</maven.build.timestamp.format>
 		<maven.build.timestamp.format>MMddHHmm</maven.build.timestamp.format>
 		<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
 		<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
+		<jedis-version>3.1.0</jedis-version>
 
 
 		<!-- 依赖版本 -->
 		<!-- 依赖版本 -->
 		<pagehelper.version>5.2.0</pagehelper.version>
 		<pagehelper.version>5.2.0</pagehelper.version>
@@ -80,6 +81,12 @@
 			<artifactId>spring-boot-starter-security</artifactId>
 			<artifactId>spring-boot-starter-security</artifactId>
 		</dependency>
 		</dependency>
 
 
+		<dependency>
+			<groupId>redis.clients</groupId>
+			<artifactId>jedis</artifactId>
+			<version>${jedis-version}</version>
+		</dependency>
+
 		<!-- druid数据库连接池 -->
 		<!-- druid数据库连接池 -->
 		<dependency>
 		<dependency>
 			<groupId>com.alibaba</groupId>
 			<groupId>com.alibaba</groupId>

+ 107 - 97
sql/mysql.sql

@@ -1,112 +1,145 @@
 -- auto-generated definition
 -- auto-generated definition
-create schema wvp collate utf8_bin;
+
+
+CREATE DATABASE `wvp` /*!40100 DEFAULT CHARACTER SET utf8mb3 COLLATE utf8mb3_bin */;
+
+use wvp;
 
 
 create table device
 create table device
 (
 (
-    deviceId           varchar(50) not null
+    deviceId      varchar(50)  not null
         primary key,
         primary key,
-    name               varchar(255) null,
-    manufacturer       varchar(255) null,
-    model              varchar(255) null,
-    firmware           varchar(255) null,
-    transport          varchar(50) null,
-    streamMode         varchar(50) null,
-    online             varchar(50) null,
-    registerTime       varchar(50) null,
-    keepaliveTime      varchar(50) null,
-    ip                 varchar(50) not null,
-    createTime         varchar(50) not null,
-    updateTime         varchar(50) not null,
-    port               int          not null,
-    expires            int          not null,
-    hostAddress        varchar(50) not null
+    name          varchar(255) null,
+    manufacturer  varchar(255) null,
+    model         varchar(255) null,
+    firmware      varchar(255) null,
+    transport     varchar(50)  null,
+    streamMode    varchar(50)  null,
+    online        varchar(50)  null,
+    registerTime  varchar(50)  null,
+    keepaliveTime varchar(50)  null,
+    ip            varchar(50)  not null,
+    createTime    varchar(50)  not null,
+    updateTime    varchar(50)  not null,
+    port          int          not null,
+    expires       int          not null,
+    hostAddress   varchar(50)  not null
 );
 );
 
 
 create table device_channel
 create table device_channel
 (
 (
-    channelId   varchar(50) not null,
+    channelId   varchar(50)  not null,
     name        varchar(255) null,
     name        varchar(255) null,
-    manufacture varchar(50) null,
-    model       varchar(50) null,
-    owner       varchar(50) null,
-    civilCode   varchar(50) null,
-    block       varchar(50) null,
-    address     varchar(50) null,
-    parentId    varchar(50) null,
+    manufacture varchar(50)  null,
+    model       varchar(50)  null,
+    owner       varchar(50)  null,
+    civilCode   varchar(50)  null,
+    block       varchar(50)  null,
+    address     varchar(50)  null,
+    parentId    varchar(50)  null,
     safetyWay   int          null,
     safetyWay   int          null,
     registerWay int          null,
     registerWay int          null,
-    certNum     varchar(50) null,
+    certNum     varchar(50)  null,
     certifiable int          null,
     certifiable int          null,
     errCode     int          null,
     errCode     int          null,
-    endTime     varchar(50) null,
-    secrecy     varchar(50) null,
-    ipAddress   varchar(50) null,
+    endTime     varchar(50)  null,
+    secrecy     varchar(50)  null,
+    ipAddress   varchar(50)  null,
     port        int          null,
     port        int          null,
     password    varchar(255) null,
     password    varchar(255) null,
     PTZType     int          null,
     PTZType     int          null,
     status      int          null,
     status      int          null,
     longitude   double       null,
     longitude   double       null,
     latitude    double       null,
     latitude    double       null,
-    streamId    varchar(50) null,
-    deviceId    varchar(50) not null,
-    parental    varchar(50) null,
-    hasAudio    bit(1)   null,
-    createTime  varchar(50) not null,
-    updateTime  varchar(50) not null,
+    streamId    varchar(50)  null,
+    deviceId    varchar(50)  not null,
+    parental    varchar(50)  null,
+    hasAudio    bit          null,
+    createTime  varchar(50)  not null,
+    updateTime  varchar(50)  not null,
     primary key (channelId, deviceId)
     primary key (channelId, deviceId)
 );
 );
 
 
 create table device_mobile_position
 create table device_mobile_position
 (
 (
-    deviceId       varchar(50) not null,
+    deviceId       varchar(50)  not null,
     deviceName     varchar(255) null,
     deviceName     varchar(255) null,
-    time           varchar(50) not null,
+    time           varchar(50)  not null,
     longitude      double       not null,
     longitude      double       not null,
     latitude       double       not null,
     latitude       double       not null,
     altitude       double       null,
     altitude       double       null,
     speed          double       null,
     speed          double       null,
     direction      double       null,
     direction      double       null,
-    reportSource   varchar(50) null,
-    geodeticSystem varchar(50) null,
-    cnLng          varchar(50) null,
-    cnLat          varchar(50) null,
+    reportSource   varchar(50)  null,
+    geodeticSystem varchar(50)  null,
+    cnLng          varchar(50)  null,
+    cnLat          varchar(50)  null,
     primary key (deviceId, time)
     primary key (deviceId, time)
 );
 );
 
 
 create table gb_stream
 create table gb_stream
 (
 (
-    app        varchar(255) not null,
-    stream     varchar(255) not null,
-    gbId       varchar(50) not null,
-    name       varchar(255) null,
-    longitude  double       null,
-    latitude   double       null,
-    streamType varchar(50) null,
-    status     int          null,
+    app           varchar(255) not null,
+    stream        varchar(255) not null,
+    gbId          varchar(50)  not null,
+    name          varchar(255) null,
+    longitude     double       null,
+    latitude      double       null,
+    streamType    varchar(50)  null,
+    mediaServerId varchar(50)  null,
+    status        int          null,
     primary key (app, stream, gbId)
     primary key (app, stream, gbId)
 );
 );
 
 
+create table media_server
+(
+    id                      varchar(255) not null
+        primary key,
+    ip                      varchar(50)  not null,
+    hookIp                  varchar(50)  not null,
+    sdpIp                   varchar(50)  not null,
+    streamIp                varchar(50)  not null,
+    httpPort                int          not null,
+    httpSSlPort             int          not null,
+    rtmpPort                int          not null,
+    rtmpSSlPort             int          not null,
+    rtpProxyPort            int          not null,
+    rtspPort                int          not null,
+    rtspSSLPort             int          not null,
+    autoConfig              int          not null,
+    secret                  varchar(50)  not null,
+    streamNoneReaderDelayMS int          not null,
+    rtpEnable               int          not null,
+    rtpPortRange            varchar(50)  not null,
+    recordAssistPort        int          not null,
+    defaultServer           int          not null,
+    createTime              varchar(50)  not null,
+    updateTime              varchar(50)  not null,
+    constraint media_server_i
+        unique (ip, httpPort)
+);
+
 create table parent_platform
 create table parent_platform
 (
 (
-    id          int auto_increment,
+    id             int auto_increment,
     enable         int          null,
     enable         int          null,
     name           varchar(255) null,
     name           varchar(255) null,
-    serverGBId     varchar(50) not null,
-    serverGBDomain varchar(50) null,
-    serverIP       varchar(50) null,
+    serverGBId     varchar(50)  not null,
+    serverGBDomain varchar(50)  null,
+    serverIP       varchar(50)  null,
     serverPort     int          null,
     serverPort     int          null,
-    deviceGBId     varchar(50) not null,
-    deviceIp       varchar(50) null,
-    devicePort     varchar(50) null,
+    deviceGBId     varchar(50)  not null,
+    deviceIp       varchar(50)  null,
+    devicePort     varchar(50)  null,
     username       varchar(255) null,
     username       varchar(255) null,
-    password       varchar(50) null,
-    expires        varchar(50) null,
-    keepTimeout    varchar(50) null,
-    transport      varchar(50) null,
-    characterSet   varchar(50) null,
+    password       varchar(50)  null,
+    expires        varchar(50)  null,
+    keepTimeout    varchar(50)  null,
+    transport      varchar(50)  null,
+    characterSet   varchar(50)  null,
     ptz            int          null,
     ptz            int          null,
     rtcp           int          null,
     rtcp           int          null,
-    status         bit(1)   null,
+    status         bit          null,
     primary key (id, serverGBId)
     primary key (id, serverGBId)
 );
 );
 
 
@@ -121,7 +154,7 @@ create table platform_gb_channel
 
 
 create table platform_gb_stream
 create table platform_gb_stream
 (
 (
-    platformId varchar(50) not null,
+    platformId varchar(50)  not null,
     app        varchar(255) not null,
     app        varchar(255) not null,
     stream     varchar(255) not null,
     stream     varchar(255) not null,
     primary key (platformId, app, stream)
     primary key (platformId, app, stream)
@@ -129,7 +162,7 @@ create table platform_gb_stream
 
 
 create table stream_proxy
 create table stream_proxy
 (
 (
-    type           varchar(50) not null,
+    type           varchar(50)  not null,
     app            varchar(255) not null,
     app            varchar(255) not null,
     stream         varchar(255) not null,
     stream         varchar(255) not null,
     url            varchar(255) null,
     url            varchar(255) null,
@@ -137,11 +170,12 @@ create table stream_proxy
     dst_url        varchar(255) null,
     dst_url        varchar(255) null,
     timeout_ms     int          null,
     timeout_ms     int          null,
     ffmpeg_cmd_key varchar(255) null,
     ffmpeg_cmd_key varchar(255) null,
-    rtp_type       varchar(50) null,
-    mediaServerId       varchar(50) null,
-    enable_hls     bit(1)   null,
-    enable_mp4     bit(1)   null,
-    enable         bit(1)   not null,
+    rtp_type       varchar(50)  null,
+    mediaServerId  varchar(50)  null,
+    enable_hls     bit          null,
+    enable_mp4     bit          null,
+    enable         bit          not null,
+    createTime     varchar(50)  not null,
     primary key (app, stream)
     primary key (app, stream)
 );
 );
 
 
@@ -149,11 +183,12 @@ create table stream_push
 (
 (
     app              varchar(255) not null,
     app              varchar(255) not null,
     stream           varchar(255) not null,
     stream           varchar(255) not null,
-    totalReaderCount varchar(50) null,
+    totalReaderCount varchar(50)  null,
     originType       int          null,
     originType       int          null,
-    originTypeStr    varchar(50) null,
+    originTypeStr    varchar(50)  null,
     createStamp      int          null,
     createStamp      int          null,
     aliveSecond      int          null,
     aliveSecond      int          null,
+    mediaServerId    varchar(50)  null,
     primary key (app, stream)
     primary key (app, stream)
 );
 );
 
 
@@ -164,31 +199,6 @@ create table user
     username    varchar(255) not null,
     username    varchar(255) not null,
     password    varchar(255) not null,
     password    varchar(255) not null,
     roleId      int          not null,
     roleId      int          not null,
-    create_time varchar(50) not null
+    create_time varchar(50)  not null
 );
 );
 
 
-insert into user (username, password, roleId, create_time) values ('admin', '21232f297a57a5a743894a0e4a801fc3', '0', '2021-04-13 14:14:57');
-
-create table media_server (
-      id          varchar(255)
-          primary key,
-      ip varchar(50) NOT NULL,
-      hookIp varchar(50) NOT NULL,
-      sdpIp varchar(50) NOT NULL,
-      streamIp varchar(50) NOT NULL,
-      httpPort int NOT NULL,
-      httpSSlPort int NOT NULL,
-      rtmpPort int NOT NULL,
-      rtmpSSlPort int NOT NULL,
-      rtpProxyPort int NOT NULL,
-      rtspPort int NOT NULL,
-      rtspSSLPort int NOT NULL,
-      autoConfig int NOT NULL,
-      secret varchar(50) NOT NULL,
-      streamNoneReaderDelayMS int NOT NULL,
-      rtpEnable int NOT NULL,
-      rtpPortRange varchar(50) NOT NULL,
-      recordAssistPort int NOT NULL,
-      createTime  varchar(50) not null,
-      updateTime  varchar(50) not null
-);

+ 6 - 0
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java

@@ -12,6 +12,8 @@ public class VideoManagerConstants {
 
 
 	public static final String MEDIA_SERVER_PREFIX = "VMP_MEDIA_SERVER_";
 	public static final String MEDIA_SERVER_PREFIX = "VMP_MEDIA_SERVER_";
 
 
+	public static final String MEDIA_SERVERS_ONLINE_PREFIX = "VMP_MEDIA_ONLINE_SERVERS";
+
 	public static final String MEDIA_STREAM_PREFIX = "VMP_MEDIA_STREAM";
 	public static final String MEDIA_STREAM_PREFIX = "VMP_MEDIA_STREAM";
 
 
 	public static final String DEVICE_PREFIX = "VMP_DEVICE_";
 	public static final String DEVICE_PREFIX = "VMP_DEVICE_";
@@ -45,4 +47,8 @@ public class VideoManagerConstants {
 	public static final String EVENT_OUTLINE_UNREGISTER = "1";
 	public static final String EVENT_OUTLINE_UNREGISTER = "1";
 	
 	
 	public static final String EVENT_OUTLINE_TIMEOUT = "2";
 	public static final String EVENT_OUTLINE_TIMEOUT = "2";
+
+	public static final String MEDIA_SSRC_USED_PREFIX = "VMP_media_used_ssrc_";
+
+	public static final String MEDIA_TRANSACTION_USED_PREFIX = "VMP_media_transaction_";
 }
 }

+ 15 - 173
src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java

@@ -1,13 +1,16 @@
 package com.genersoft.iot.vmp.conf;
 package com.genersoft.iot.vmp.conf;
 
 
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
+import com.genersoft.iot.vmp.gb28181.session.SsrcConfig;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.util.StringUtils;
 import org.springframework.util.StringUtils;
 
 
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
 @Configuration("mediaConfig")
 @Configuration("mediaConfig")
-public class MediaConfig implements IMediaServerItem {
+public class MediaConfig{
 
 
     @Value("${media.id:}")
     @Value("${media.id:}")
     private String id;
     private String id;
@@ -21,6 +24,9 @@ public class MediaConfig implements IMediaServerItem {
     @Value("${sip.ip}")
     @Value("${sip.ip}")
     private String sipIp;
     private String sipIp;
 
 
+    @Value("${sip.domain}")
+    private String sipDomain;
+
     @Value("${media.sdp-ip:${media.ip}}")
     @Value("${media.sdp-ip:${media.ip}}")
     private String sdpIp;
     private String sdpIp;
 
 
@@ -66,31 +72,14 @@ public class MediaConfig implements IMediaServerItem {
     @Value("${media.record-assist-port:0}")
     @Value("${media.record-assist-port:0}")
     private Integer recordAssistPort = 0;
     private Integer recordAssistPort = 0;
 
 
-    private String updateTime;
-
-    private String createTime;
-
-    private boolean docker = false;
-
-    private int count;
-
-
     public String getId() {
     public String getId() {
         return id;
         return id;
     }
     }
 
 
-    public void setId(String id) {
-        this.id = id;
-    }
-    
     public String getIp() {
     public String getIp() {
         return ip;
         return ip;
     }
     }
 
 
-    public void setIp(String ip) {
-        this.ip = ip;
-    }
-
     public String getHookIp() {
     public String getHookIp() {
         if (StringUtils.isEmpty(hookIp)){
         if (StringUtils.isEmpty(hookIp)){
             return sipIp;
             return sipIp;
@@ -100,78 +89,26 @@ public class MediaConfig implements IMediaServerItem {
 
 
     }
     }
 
 
-    public void setHookIp(String hookIp) {
-        this.hookIp = hookIp;
-    }
-
     public String getSipIp() {
     public String getSipIp() {
         return sipIp;
         return sipIp;
     }
     }
 
 
-    public void setSipIp(String sipIp) {
-        this.sipIp = sipIp;
-    }
-
-    public void setSdpIp(String sdpIp) {
-        this.sdpIp = sdpIp;
-    }
-
-    public void setStreamIp(String streamIp) {
-        this.streamIp = streamIp;
-    }
-
     public int getHttpPort() {
     public int getHttpPort() {
         return httpPort;
         return httpPort;
     }
     }
 
 
-    @Override
-    public void setHttpPort(int httpPort) {
-
-    }
-
-    public void setHttpPort(Integer httpPort) {
-        this.httpPort = httpPort;
-    }
-
     public int getHttpSSlPort() {
     public int getHttpSSlPort() {
         return httpSSlPort;
         return httpSSlPort;
     }
     }
 
 
-    @Override
-    public void setHttpSSlPort(int httpSSlPort) {
-
-    }
-
-    public void setHttpSSlPort(Integer httpSSlPort) {
-        this.httpSSlPort = httpSSlPort;
-    }
-
     public int getRtmpPort() {
     public int getRtmpPort() {
         return rtmpPort;
         return rtmpPort;
     }
     }
-
-    @Override
-    public void setRtmpPort(int rtmpPort) {
-
-    }
-
-    public void setRtmpPort(Integer rtmpPort) {
-        this.rtmpPort = rtmpPort;
-    }
-
+    
     public int getRtmpSSlPort() {
     public int getRtmpSSlPort() {
         return rtmpSSlPort;
         return rtmpSSlPort;
     }
     }
 
 
-    @Override
-    public void setRtmpSSlPort(int rtmpSSlPort) {
-
-    }
-
-    public void setRtmpSSlPort(Integer rtmpSSlPort) {
-        this.rtmpSSlPort = rtmpSSlPort;
-    }
-
     public int getRtpProxyPort() {
     public int getRtpProxyPort() {
         if (rtpProxyPort == null) {
         if (rtpProxyPort == null) {
             return 0;
             return 0;
@@ -181,104 +118,38 @@ public class MediaConfig implements IMediaServerItem {
 
 
     }
     }
 
 
-    @Override
-    public void setRtpProxyPort(int rtpProxyPort) {
-
-    }
-
-    public void setRtpProxyPort(Integer rtpProxyPort) {
-        this.rtpProxyPort = rtpProxyPort;
-    }
-
     public int getRtspPort() {
     public int getRtspPort() {
         return rtspPort;
         return rtspPort;
     }
     }
 
 
-    @Override
-    public void setRtspPort(int rtspPort) {
-
-    }
-
-    public void setRtspPort(Integer rtspPort) {
-        this.rtspPort = rtspPort;
-    }
-
     public int getRtspSSLPort() {
     public int getRtspSSLPort() {
         return rtspSSLPort;
         return rtspSSLPort;
     }
     }
 
 
-    @Override
-    public void setRtspSSLPort(int rtspSSLPort) {
-
-    }
-
-    public void setRtspSSLPort(Integer rtspSSLPort) {
-        this.rtspSSLPort = rtspSSLPort;
-    }
-
     public boolean isAutoConfig() {
     public boolean isAutoConfig() {
         return autoConfig;
         return autoConfig;
     }
     }
 
 
-    public void setAutoConfig(boolean autoConfig) {
-        this.autoConfig = autoConfig;
-    }
-
     public String getSecret() {
     public String getSecret() {
         return secret;
         return secret;
     }
     }
 
 
-    public void setSecret(String secret) {
-        this.secret = secret;
-    }
-
     public String getStreamNoneReaderDelayMS() {
     public String getStreamNoneReaderDelayMS() {
         return streamNoneReaderDelayMS;
         return streamNoneReaderDelayMS;
     }
     }
 
 
-    public void setStreamNoneReaderDelayMS(String streamNoneReaderDelayMS) {
-        this.streamNoneReaderDelayMS = streamNoneReaderDelayMS;
-    }
-
     public boolean isRtpEnable() {
     public boolean isRtpEnable() {
         return rtpEnable;
         return rtpEnable;
     }
     }
 
 
-    public void setRtpEnable(boolean rtpEnable) {
-        this.rtpEnable = rtpEnable;
-    }
-
     public String getRtpPortRange() {
     public String getRtpPortRange() {
         return rtpPortRange;
         return rtpPortRange;
     }
     }
-
-    public void setRtpPortRange(String rtpPortRange) {
-        this.rtpPortRange = rtpPortRange;
-    }
-
+    
     public int getRecordAssistPort() {
     public int getRecordAssistPort() {
         return recordAssistPort;
         return recordAssistPort;
     }
     }
 
 
-    @Override
-    public void setRecordAssistPort(int recordAssistPort) {
-
-    }
-
-    public void setRecordAssistPort(Integer recordAssistPort) {
-        this.recordAssistPort = recordAssistPort;
-    }
-
-    @Override
-    public boolean isDocker() {
-        return docker;
-    }
-
-    @Override
-    public void setDocker(boolean docker) {
-        this.docker = docker;
-    }
-
     public String getSdpIp() {
     public String getSdpIp() {
         if (StringUtils.isEmpty(sdpIp)){
         if (StringUtils.isEmpty(sdpIp)){
             return ip;
             return ip;
@@ -295,13 +166,11 @@ public class MediaConfig implements IMediaServerItem {
         }
         }
     }
     }
 
 
-
-
     public MediaServerItem getMediaSerItem(){
     public MediaServerItem getMediaSerItem(){
         MediaServerItem mediaServerItem = new MediaServerItem();
         MediaServerItem mediaServerItem = new MediaServerItem();
         mediaServerItem.setId(id);
         mediaServerItem.setId(id);
         mediaServerItem.setIp(ip);
         mediaServerItem.setIp(ip);
-        mediaServerItem.setDocker(true);
+        mediaServerItem.setDefaultServer(true);
         mediaServerItem.setHookIp(hookIp);
         mediaServerItem.setHookIp(hookIp);
         mediaServerItem.setSdpIp(sdpIp);
         mediaServerItem.setSdpIp(sdpIp);
         mediaServerItem.setStreamIp(streamIp);
         mediaServerItem.setStreamIp(streamIp);
@@ -318,39 +187,12 @@ public class MediaConfig implements IMediaServerItem {
         mediaServerItem.setRtpEnable(rtpEnable);
         mediaServerItem.setRtpEnable(rtpEnable);
         mediaServerItem.setRtpPortRange(rtpPortRange);
         mediaServerItem.setRtpPortRange(rtpPortRange);
         mediaServerItem.setRecordAssistPort(recordAssistPort);
         mediaServerItem.setRecordAssistPort(recordAssistPort);
-        mediaServerItem.setCreateTime(createTime);
-        mediaServerItem.setUpdateTime(updateTime);
-        mediaServerItem.setCount(count);
-        return mediaServerItem;
-    }
-
-    @Override
-    public String getUpdateTime() {
-        return updateTime;
-    }
 
 
-    @Override
-    public void setUpdateTime(String updateTime) {
-        this.updateTime = updateTime;
-    }
+        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        mediaServerItem.setCreateTime(format.format(new Date(System.currentTimeMillis())));
+        mediaServerItem.setUpdateTime(format.format(new Date(System.currentTimeMillis())));
 
 
-    @Override
-    public String getCreateTime() {
-        return createTime;
-    }
-
-    @Override
-    public void setCreateTime(String createTime) {
-        this.createTime = createTime;
-    }
-
-    @Override
-    public int getCount() {
-        return count;
+        return mediaServerItem;
     }
     }
 
 
-    @Override
-    public void setCount(int count) {
-        this.count = count;
-    }
 }
 }

+ 10 - 10
src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java

@@ -1,6 +1,6 @@
 package com.genersoft.iot.vmp.conf;
 package com.genersoft.iot.vmp.conf;
 
 
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
+import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import org.apache.catalina.connector.ClientAbortException;
 import org.apache.catalina.connector.ClientAbortException;
 import org.apache.http.HttpHost;
 import org.apache.http.HttpHost;
@@ -49,7 +49,7 @@ public class ProxyServletConfig {
         @Override
         @Override
         protected String rewriteQueryStringFromRequest(HttpServletRequest servletRequest, String queryString) {
         protected String rewriteQueryStringFromRequest(HttpServletRequest servletRequest, String queryString) {
             String queryStr = super.rewriteQueryStringFromRequest(servletRequest, queryString);
             String queryStr = super.rewriteQueryStringFromRequest(servletRequest, queryString);
-            IMediaServerItem mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI());
+            MediaServerItem mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI());
             if (mediaInfo != null) {
             if (mediaInfo != null) {
                 if (!StringUtils.isEmpty(queryStr)) {
                 if (!StringUtils.isEmpty(queryStr)) {
                     queryStr += "&secret=" + mediaInfo.getSecret();
                     queryStr += "&secret=" + mediaInfo.getSecret();
@@ -88,7 +88,7 @@ public class ProxyServletConfig {
         @Override
         @Override
         protected String getTargetUri(HttpServletRequest servletRequest) {
         protected String getTargetUri(HttpServletRequest servletRequest) {
             String requestURI = servletRequest.getRequestURI();
             String requestURI = servletRequest.getRequestURI();
-            IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
+            MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
 
 
             String uri = null;
             String uri = null;
             if (mediaInfo != null) {
             if (mediaInfo != null) {
@@ -106,7 +106,7 @@ public class ProxyServletConfig {
         @Override
         @Override
         protected HttpHost getTargetHost(HttpServletRequest servletRequest) {
         protected HttpHost getTargetHost(HttpServletRequest servletRequest) {
             String requestURI = servletRequest.getRequestURI();
             String requestURI = servletRequest.getRequestURI();
-            IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
+            MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
             HttpHost host;
             HttpHost host;
             if (mediaInfo != null) {
             if (mediaInfo != null) {
                 host = new HttpHost(mediaInfo.getIp(), mediaInfo.getHttpPort());
                 host = new HttpHost(mediaInfo.getIp(), mediaInfo.getHttpPort());
@@ -120,7 +120,7 @@ public class ProxyServletConfig {
         /**
         /**
          * 根据uri获取流媒体信息
          * 根据uri获取流媒体信息
          */
          */
-        IMediaServerItem getMediaInfoByUri(String uri){
+        MediaServerItem getMediaInfoByUri(String uri){
             String[] split = uri.split("/");
             String[] split = uri.split("/");
             String mediaServerId = split[2];
             String mediaServerId = split[2];
             return mediaServerService.getOne(mediaServerId);
             return mediaServerService.getOne(mediaServerId);
@@ -132,7 +132,7 @@ public class ProxyServletConfig {
         @Override
         @Override
         protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) {
         protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) {
             String requestURI = servletRequest.getRequestURI();
             String requestURI = servletRequest.getRequestURI();
-            IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
+            MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
             String url = super.rewriteUrlFromRequest(servletRequest);
             String url = super.rewriteUrlFromRequest(servletRequest);
             if (mediaInfo == null) {
             if (mediaInfo == null) {
                 return  url;
                 return  url;
@@ -186,7 +186,7 @@ public class ProxyServletConfig {
         @Override
         @Override
         protected String getTargetUri(HttpServletRequest servletRequest) {
         protected String getTargetUri(HttpServletRequest servletRequest) {
             String requestURI = servletRequest.getRequestURI();
             String requestURI = servletRequest.getRequestURI();
-            IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
+            MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
 
 
             String uri = null;
             String uri = null;
             if (mediaInfo != null) {
             if (mediaInfo != null) {
@@ -204,7 +204,7 @@ public class ProxyServletConfig {
         @Override
         @Override
         protected HttpHost getTargetHost(HttpServletRequest servletRequest) {
         protected HttpHost getTargetHost(HttpServletRequest servletRequest) {
             String requestURI = servletRequest.getRequestURI();
             String requestURI = servletRequest.getRequestURI();
-            IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
+            MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
             HttpHost host;
             HttpHost host;
             if (mediaInfo != null) {
             if (mediaInfo != null) {
                 host = new HttpHost(mediaInfo.getIp(), mediaInfo.getRecordAssistPort());
                 host = new HttpHost(mediaInfo.getIp(), mediaInfo.getRecordAssistPort());
@@ -218,7 +218,7 @@ public class ProxyServletConfig {
         /**
         /**
          * 根据uri获取流媒体信息
          * 根据uri获取流媒体信息
          */
          */
-        IMediaServerItem getMediaInfoByUri(String uri){
+        MediaServerItem getMediaInfoByUri(String uri){
             String[] split = uri.split("/");
             String[] split = uri.split("/");
             String mediaServerId = split[2];
             String mediaServerId = split[2];
             return mediaServerService.getOne(mediaServerId);
             return mediaServerService.getOne(mediaServerId);
@@ -230,7 +230,7 @@ public class ProxyServletConfig {
         @Override
         @Override
         protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) {
         protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) {
             String requestURI = servletRequest.getRequestURI();
             String requestURI = servletRequest.getRequestURI();
-            IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
+            MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
             String url = super.rewriteUrlFromRequest(servletRequest);
             String url = super.rewriteUrlFromRequest(servletRequest);
             if (mediaInfo == null) {
             if (mediaInfo == null) {
                 return  url;
                 return  url;

+ 36 - 1
src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java

@@ -1,5 +1,7 @@
 package com.genersoft.iot.vmp.conf;
 package com.genersoft.iot.vmp.conf;
 
 
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.cache.annotation.CachingConfigurerSupport;
 import org.springframework.cache.annotation.CachingConfigurerSupport;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Configuration;
@@ -10,6 +12,8 @@ import org.springframework.data.redis.serializer.StringRedisSerializer;
 
 
 import com.alibaba.fastjson.parser.ParserConfig;
 import com.alibaba.fastjson.parser.ParserConfig;
 import com.genersoft.iot.vmp.utils.redis.FastJsonRedisSerializer;
 import com.genersoft.iot.vmp.utils.redis.FastJsonRedisSerializer;
+import redis.clients.jedis.JedisPool;
+import redis.clients.jedis.JedisPoolConfig;
 
 
 /**
 /**
  * @Description:Redis中间件配置类,使用spring-data-redis集成,自动从application.yml中加载redis配置
  * @Description:Redis中间件配置类,使用spring-data-redis集成,自动从application.yml中加载redis配置
@@ -20,6 +24,37 @@ import com.genersoft.iot.vmp.utils.redis.FastJsonRedisSerializer;
 @Configuration
 @Configuration
 public class RedisConfig extends CachingConfigurerSupport {
 public class RedisConfig extends CachingConfigurerSupport {
 
 
+	@Value("${spring.redis.host}")
+	private String host;
+	@Value("${spring.redis.port}")
+	private int port;
+	@Value("${spring.redis.database}")
+	private int database;
+	@Value("${spring.redis.password}")
+	private String password;
+	@Value("${spring.redis.timeout}")
+	private int timeout;
+	@Value("${spring.redis.poolMaxTotal:1000}")
+	private int poolMaxTotal;
+	@Value("${spring.redis.poolMaxIdle:500}")
+	private int poolMaxIdle;
+	@Value("${spring.redis.poolMaxWait:5}")
+	private int poolMaxWait;
+
+	@Bean
+	public JedisPool jedisPool() {
+		if (StringUtils.isBlank(password)) {
+			password = null;
+		}
+		JedisPoolConfig poolConfig = new JedisPoolConfig();
+		poolConfig.setMaxIdle(poolMaxIdle);
+		poolConfig.setMaxTotal(poolMaxTotal);
+		// 秒转毫秒
+		poolConfig.setMaxWaitMillis(poolMaxWait * 1000L);
+		JedisPool jp = new JedisPool(poolConfig, host, port, timeout * 1000, password, database);
+		return jp;
+	}
+
 	@Bean("redisTemplate")
 	@Bean("redisTemplate")
 	public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
 	public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
 		RedisTemplate<Object, Object> template = new RedisTemplate<>();
 		RedisTemplate<Object, Object> template = new RedisTemplate<>();
@@ -34,7 +69,7 @@ public class RedisConfig extends CachingConfigurerSupport {
 		template.setHashKeySerializer(new StringRedisSerializer());
 		template.setHashKeySerializer(new StringRedisSerializer());
 		template.setConnectionFactory(redisConnectionFactory);
 		template.setConnectionFactory(redisConnectionFactory);
 		// 使用fastjson时需设置此项,否则会报异常not support type
 		// 使用fastjson时需设置此项,否则会报异常not support type
-		ParserConfig.getGlobalInstance().setAutoTypeSupport(true); 
+		ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
 		return template;
 		return template;
 	}
 	}
 
 

+ 0 - 31
src/main/java/com/genersoft/iot/vmp/conf/SipDeviceRunner.java

@@ -1,31 +0,0 @@
-package com.genersoft.iot.vmp.conf;
-
-import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
-import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.CommandLineRunner;
-import org.springframework.core.annotation.Order;
-import org.springframework.stereotype.Component;
-
-
-/**
- * 系统启动时控制设备离线
- */
-@Component
-@Order(value=4)
-public class SipDeviceRunner implements CommandLineRunner {
-
-    @Autowired
-    private IVideoManagerStorager storager;
-
-    @Autowired
-    private IRedisCatchStorage redisCatchStorage;
-
-    @Override
-    public void run(String... args) throws Exception {
-        // 设置所有设备离线
-        storager.outlineForAll();
-        // 设置所有设备离线
-        redisCatchStorage.outlineForAll();
-    }
-}

+ 13 - 15
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java

@@ -12,6 +12,7 @@ import javax.sip.header.CallIdHeader;
 import javax.sip.message.Response;
 import javax.sip.message.Response;
 
 
 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
+import gov.nist.javax.sip.SipProviderImpl;
 import org.slf4j.Logger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -39,7 +40,7 @@ public class SipLayer implements SipListener {
 	@Autowired
 	@Autowired
 	private SipSubscribe sipSubscribe;
 	private SipSubscribe sipSubscribe;
 
 
-	private SipStack sipStack;
+	private SipStackImpl sipStack;
 
 
 	private SipFactory sipFactory;
 	private SipFactory sipFactory;
 
 
@@ -52,7 +53,7 @@ public class SipLayer implements SipListener {
 	private ThreadPoolExecutor initSipServer() {
 	private ThreadPoolExecutor initSipServer() {
 		
 		
 		int processThreadNum = Runtime.getRuntime().availableProcessors() * 10;
 		int processThreadNum = Runtime.getRuntime().availableProcessors() * 10;
-		LinkedBlockingQueue<Runnable> processQueue = new LinkedBlockingQueue<Runnable>(10000);
+		LinkedBlockingQueue<Runnable> processQueue = new LinkedBlockingQueue<>(10000);
 		processThreadPool = new ThreadPoolExecutor(processThreadNum,processThreadNum,
 		processThreadPool = new ThreadPoolExecutor(processThreadNum,processThreadNum,
 				0L,TimeUnit.MILLISECONDS,processQueue,
 				0L,TimeUnit.MILLISECONDS,processQueue,
 				new ThreadPoolExecutor.CallerRunsPolicy());
 				new ThreadPoolExecutor.CallerRunsPolicy());
@@ -88,17 +89,14 @@ public class SipLayer implements SipListener {
 
 
 	@Bean("tcpSipProvider")
 	@Bean("tcpSipProvider")
 	@DependsOn("sipStack")
 	@DependsOn("sipStack")
-	private SipProvider startTcpListener() {
+	private SipProviderImpl startTcpListener() {
 		ListeningPoint tcpListeningPoint = null;
 		ListeningPoint tcpListeningPoint = null;
-		SipProvider tcpSipProvider  = null;
+		SipProviderImpl tcpSipProvider  = null;
 		try {
 		try {
 			tcpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getSipPort(), "TCP");
 			tcpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getSipPort(), "TCP");
-			tcpSipProvider = sipStack.createSipProvider(tcpListeningPoint);
+			tcpSipProvider = (SipProviderImpl)sipStack.createSipProvider(tcpListeningPoint);
 			tcpSipProvider.addSipListener(this);
 			tcpSipProvider.addSipListener(this);
 			logger.info("Sip Server TCP 启动成功 port {" + sipConfig.getMonitorIp() + ":" + sipConfig.getSipPort() + "}");
 			logger.info("Sip Server TCP 启动成功 port {" + sipConfig.getMonitorIp() + ":" + sipConfig.getSipPort() + "}");
-//		} catch (TransportNotSupportedException | InvalidArgumentException | TooManyListenersException | ObjectInUseException e) {
-//			logger.error(String.format("创建SIP服务失败: %s", e.getMessage()));
-//		}
 		} catch (TransportNotSupportedException e) {
 		} catch (TransportNotSupportedException e) {
 			e.printStackTrace();
 			e.printStackTrace();
 		} catch (InvalidArgumentException e) {
 		} catch (InvalidArgumentException e) {
@@ -114,13 +112,14 @@ public class SipLayer implements SipListener {
 	
 	
 	@Bean("udpSipProvider")
 	@Bean("udpSipProvider")
 	@DependsOn("sipStack")
 	@DependsOn("sipStack")
-	private SipProvider startUdpListener() {
+	private SipProviderImpl startUdpListener() {
 		ListeningPoint udpListeningPoint = null;
 		ListeningPoint udpListeningPoint = null;
-		SipProvider udpSipProvider = null;
+		SipProviderImpl udpSipProvider = null;
 		try {
 		try {
 			udpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getSipPort(), "UDP");
 			udpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getSipPort(), "UDP");
-			udpSipProvider = sipStack.createSipProvider(udpListeningPoint);
+			udpSipProvider = (SipProviderImpl)sipStack.createSipProvider(udpListeningPoint);
 			udpSipProvider.addSipListener(this);
 			udpSipProvider.addSipListener(this);
+//			udpSipProvider.setAutomaticDialogSupportEnabled(false);
 		} catch (TransportNotSupportedException e) {
 		} catch (TransportNotSupportedException e) {
 			e.printStackTrace();
 			e.printStackTrace();
 		} catch (InvalidArgumentException e) {
 		} catch (InvalidArgumentException e) {
@@ -141,7 +140,7 @@ public class SipLayer implements SipListener {
 	 */
 	 */
 	@Override
 	@Override
 	public void processRequest(RequestEvent evt) {
 	public void processRequest(RequestEvent evt) {
-//		logger.debug(evt.getRequest().toString());
+		logger.debug(evt.getRequest().toString());
 		// 由于jainsip是单线程程序,为提高性能并发处理
 		// 由于jainsip是单线程程序,为提高性能并发处理
 		processThreadPool.execute(() -> {
 		processThreadPool.execute(() -> {
 			if (processorFactory != null) {
 			if (processorFactory != null) {
@@ -153,7 +152,7 @@ public class SipLayer implements SipListener {
 	@Override
 	@Override
 	public void processResponse(ResponseEvent evt) {
 	public void processResponse(ResponseEvent evt) {
 		Response response = evt.getResponse();
 		Response response = evt.getResponse();
-//		logger.debug(evt.getResponse().toString());
+		logger.debug(evt.getResponse().toString());
 		int status = response.getStatusCode();
 		int status = response.getStatusCode();
 		if (((status >= 200) && (status < 300)) || status == 401) { // Success!
 		if (((status >= 200) && (status < 300)) || status == 401) { // Success!
 			ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt);
 			ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt);
@@ -163,6 +162,7 @@ public class SipLayer implements SipListener {
 				// TODO Auto-generated catch block
 				// TODO Auto-generated catch block
 				e.printStackTrace();
 				e.printStackTrace();
 			}
 			}
+
 			if (evt.getResponse() != null && sipSubscribe.getOkSubscribesSize() > 0 ) {
 			if (evt.getResponse() != null && sipSubscribe.getOkSubscribesSize() > 0 ) {
 				CallIdHeader callIdHeader = (CallIdHeader)evt.getResponse().getHeader(CallIdHeader.NAME);
 				CallIdHeader callIdHeader = (CallIdHeader)evt.getResponse().getHeader(CallIdHeader.NAME);
 				if (callIdHeader != null) {
 				if (callIdHeader != null) {
@@ -220,7 +220,6 @@ public class SipLayer implements SipListener {
 	@Override
 	@Override
 	public void processIOException(IOExceptionEvent exceptionEvent) {
 	public void processIOException(IOExceptionEvent exceptionEvent) {
 		// TODO Auto-generated method stub
 		// TODO Auto-generated method stub
-
 	}
 	}
 
 
 	/**
 	/**
@@ -236,7 +235,6 @@ public class SipLayer implements SipListener {
 	@Override
 	@Override
 	public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
 	public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
 		// TODO Auto-generated method stub
 		// TODO Auto-generated method stub
-
 	}
 	}
 
 
 	/**
 	/**

+ 70 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java

@@ -0,0 +1,70 @@
+package com.genersoft.iot.vmp.gb28181.bean;
+
+import javax.sip.message.Request;
+
+public class SsrcTransaction {
+
+    private String deviceId;
+    private String channelId;
+    private String ssrc;
+    private String streamId;
+    private byte[] transaction;
+    private byte[] dialog;
+    private String mediaServerId;
+
+    public String getDeviceId() {
+        return deviceId;
+    }
+
+    public void setDeviceId(String deviceId) {
+        this.deviceId = deviceId;
+    }
+
+    public String getChannelId() {
+        return channelId;
+    }
+
+    public void setChannelId(String channelId) {
+        this.channelId = channelId;
+    }
+
+    public String getSsrc() {
+        return ssrc;
+    }
+
+    public void setSsrc(String ssrc) {
+        this.ssrc = ssrc;
+    }
+
+    public String getStreamId() {
+        return streamId;
+    }
+
+    public void setStreamId(String streamId) {
+        this.streamId = streamId;
+    }
+
+    public byte[] getTransaction() {
+        return transaction;
+    }
+
+    public void setTransaction(byte[] transaction) {
+        this.transaction = transaction;
+    }
+
+    public byte[] getDialog() {
+        return dialog;
+    }
+
+    public void setDialog(byte[] dialog) {
+        this.dialog = dialog;
+    }
+
+    public String getMediaServerId() {
+        return mediaServerId;
+    }
+
+    public void setMediaServerId(String mediaServerId) {
+        this.mediaServerId = mediaServerId;
+    }
+}

+ 1 - 2
src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java

@@ -6,7 +6,6 @@ import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@@ -77,7 +76,7 @@ public class PlatformNotRegisterEventLister implements ApplicationListener<Platf
                 }
                 }
                 stream.append(sendRtpItem.getStreamId());
                 stream.append(sendRtpItem.getStreamId());
                 redisCatchStorage.deleteSendRTPServer(event.getPlatformGbID(), sendRtpItem.getChannelId());
                 redisCatchStorage.deleteSendRTPServer(event.getPlatformGbID(), sendRtpItem.getChannelId());
-                IMediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
+                MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
                 Map<String, Object> param = new HashMap<>();
                 Map<String, Object> param = new HashMap<>();
                 param.put("vhost", "__defaultVhost__");
                 param.put("vhost", "__defaultVhost__");
                 param.put("app", app.toString());
                 param.put("app", app.toString());

+ 140 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/session/SsrcConfig.java

@@ -0,0 +1,140 @@
+package com.genersoft.iot.vmp.gb28181.session;
+
+import com.genersoft.iot.vmp.utils.ConfigConst;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+
+public class SsrcConfig {
+
+    /**
+     * zlm流媒体服务器Id
+     */
+    private String mediaServerId;
+
+    private String ssrcPrefix;
+    /**
+     * zlm流媒体服务器已用会话句柄
+     */
+    private List<String> isUsed;
+    /**
+     * zlm流媒体服务器可用会话句柄
+     */
+    private List<String> notUsed;
+
+    public SsrcConfig() {
+    }
+
+    public SsrcConfig(String mediaServerId, Set<String> usedSet, String sipDomain) {
+        this.mediaServerId = mediaServerId;
+        this.isUsed = new ArrayList<>();
+        this.ssrcPrefix = sipDomain.substring(3, 8);
+        this.notUsed = new ArrayList<>();
+        for (int i = 1; i < ConfigConst.MAX_STRTEAM_COUNT; i++) {
+            String ssrc;
+            if (i < 10) {
+                ssrc = "000" + i;
+            } else if (i < 100) {
+                ssrc = "00" + i;
+            } else if (i < 1000) {
+                ssrc = "0" + i;
+            } else {
+                ssrc = String.valueOf(i);
+            }
+            if (null == usedSet || !usedSet.contains(ssrc)) {
+                this.notUsed.add(ssrc);
+            } else {
+                this.isUsed.add(ssrc);
+            }
+        }
+    }
+
+
+    /**
+     * 获取视频预览的SSRC值,第一位固定为0
+     * @return ssrc
+     */
+    public String getPlaySsrc() {
+        return "0" + getSsrcPrefix() + getSN();
+    }
+
+    /**
+     * 获取录像回放的SSRC值,第一位固定为1
+     *
+     */
+    public String getPlayBackSsrc() {
+        return "1" + getSsrcPrefix() + getSN();
+    }
+
+    /**
+     * 释放ssrc,主要用完的ssrc一定要释放,否则会耗尽
+     * @param ssrc 需要重置的ssrc
+     */
+    public void releaseSsrc(String ssrc) {
+        if (ssrc == null) {
+            return;
+        }
+        String sn = ssrc.substring(6);
+        try {
+            isUsed.remove(sn);
+            notUsed.add(sn);
+        }catch (NullPointerException e){
+            System.out.printf("11111");
+        }
+    }
+
+    /**
+     * 获取后四位数SN,随机数
+     *
+     */
+    private String getSN() {
+        String sn = null;
+        int index = 0;
+        if (notUsed.size() == 0) {
+            throw new RuntimeException("ssrc已经用完");
+        } else if (notUsed.size() == 1) {
+            sn = notUsed.get(0);
+        } else {
+            index = new Random().nextInt(notUsed.size() - 1);
+            sn = notUsed.get(index);
+        }
+        notUsed.remove(index);
+        isUsed.add(sn);
+        return sn;
+    }
+
+    public String getSsrcPrefix() {
+        return ssrcPrefix;
+    }
+
+    public String getMediaServerId() {
+        return mediaServerId;
+    }
+
+    public void setMediaServerId(String mediaServerId) {
+        this.mediaServerId = mediaServerId;
+    }
+
+    public void setSsrcPrefix(String ssrcPrefix) {
+        this.ssrcPrefix = ssrcPrefix;
+    }
+
+    public List<String> getIsUsed() {
+        return isUsed;
+    }
+
+    public void setIsUsed(List<String> isUsed) {
+        this.isUsed = isUsed;
+    }
+
+    public List<String> getNotUsed() {
+        return notUsed;
+    }
+
+    public void setNotUsed(List<String> notUsed) {
+        this.notUsed = notUsed;
+    }
+
+}

+ 0 - 101
src/main/java/com/genersoft/iot/vmp/gb28181/session/SsrcUtil.java

@@ -1,101 +0,0 @@
-package com.genersoft.iot.vmp.gb28181.session;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-
-import com.genersoft.iot.vmp.conf.SipConfig;
-import com.genersoft.iot.vmp.utils.SpringBeanFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * @Description:SIP信令中的SSRC工具类。SSRC值由10位十进制整数组成的字符串,第一位为0代表实况,为1则代表回放;第二位至第六位由监控域ID的第4位到第8位组成;最后4位为不重复的4个整数
- * @author: swwheihei
- * @date: 2020年5月10日 上午11:57:57
- */
-public class SsrcUtil {
-
-	private final static Logger logger = LoggerFactory.getLogger(SsrcUtil.class);
-
-	private static String ssrcPrefix;
-
-	private static List<String> isUsed;
-
-	private static List<String> notUsed;
-
-	private static void init() {
-		SipConfig sipConfig = (SipConfig) SpringBeanFactory.getBean("sipConfig");
-		ssrcPrefix = sipConfig.getSipDomain().substring(3, 8);
-		isUsed = new ArrayList<String>();
-		notUsed = new ArrayList<String>();
-		for (int i = 1; i < 10000; i++) {
-			if (i < 10) {
-				notUsed.add("000" + i);
-			} else if (i < 100) {
-				notUsed.add("00" + i);
-			} else if (i < 1000) {
-				notUsed.add("0" + i);
-			} else {
-				notUsed.add(String.valueOf(i));
-			}
-		}
-	}
-
-	/**
-	 * 获取视频预览的SSRC值,第一位固定为0
-	 * 
-	 */
-	public static String getPlaySsrc() {
-		return "0" + getSsrcPrefix() + getSN();
-	}
-
-	/**
-	 * 获取录像回放的SSRC值,第一位固定为1
-	 * 
-	 */
-	public static String getPlayBackSsrc() {
-		return "1" + getSsrcPrefix() + getSN();
-	}
-
-	/**
-	 * 释放ssrc,主要用完的ssrc一定要释放,否则会耗尽
-	 * 
-	 */
-	public static void releaseSsrc(String ssrc) {
-		if (ssrc == null) {
-			logger.error("要释放ssrc为null");
-			return;
-		}
-		String sn = ssrc.substring(6);
-		isUsed.remove(sn);
-		notUsed.add(sn);
-	}
-
-	/**
-	 * 获取后四位数SN,随机数
-	 * 
-	 */
-	private static String getSN() {
-		String sn = null;
-		int index = 0;
-		if (notUsed.size() == 0) {
-			throw new RuntimeException("ssrc已经用完");
-		} else if (notUsed.size() == 1) {
-			sn = notUsed.get(0);
-		} else {
-			index = new Random().nextInt(notUsed.size() - 1);
-			sn = notUsed.get(index);
-		}
-		notUsed.remove(index);
-		isUsed.add(sn);
-		return sn;
-	}
-
-	private static String getSsrcPrefix() {
-		if (ssrcPrefix == null) {
-			init();
-		}
-		return ssrcPrefix;
-	}
-}

+ 80 - 31
src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java

@@ -1,9 +1,23 @@
 package com.genersoft.iot.vmp.gb28181.session;
 package com.genersoft.iot.vmp.gb28181.session;
 
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentHashMap;
 
 
 import javax.sip.ClientTransaction;
 import javax.sip.ClientTransaction;
+import javax.sip.Dialog;
+import javax.sip.message.Request;
 
 
+import com.genersoft.iot.vmp.common.VideoManagerConstants;
+import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
+import com.genersoft.iot.vmp.service.IMediaServerService;
+import com.genersoft.iot.vmp.utils.SerializeUtils;
+import com.genersoft.iot.vmp.utils.redis.JedisUtil;
+import com.genersoft.iot.vmp.utils.redis.RedisUtil;
+import gov.nist.javax.sip.stack.SIPDialog;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
 
 
 /**    
 /**    
@@ -14,50 +28,85 @@ import org.springframework.stereotype.Component;
 @Component
 @Component
 public class VideoStreamSessionManager {
 public class VideoStreamSessionManager {
 
 
-	private ConcurrentHashMap<String, ClientTransaction> sessionMap = new ConcurrentHashMap<>();
-	private ConcurrentHashMap<String, String> ssrcMap = new ConcurrentHashMap<>();
-	private ConcurrentHashMap<String, String> streamIdMap = new ConcurrentHashMap<>();
+	@Autowired
+	private RedisUtil redisUtil;
 
 
-	public String createPlaySsrc(){
-		return SsrcUtil.getPlaySsrc();
-	}
-	
-	public String createPlayBackSsrc(){
-		return SsrcUtil.getPlayBackSsrc();
+	public void put(String deviceId, String channelId ,String ssrc, String streamId, String mediaServerId, ClientTransaction transaction){
+		SsrcTransaction ssrcTransaction = new SsrcTransaction();
+		ssrcTransaction.setDeviceId(deviceId);
+		ssrcTransaction.setChannelId(channelId);
+		ssrcTransaction.setStreamId(streamId);
+		byte[] transactionByteArray = SerializeUtils.serialize(transaction);
+		ssrcTransaction.setTransaction(transactionByteArray);
+		ssrcTransaction.setSsrc(ssrc);
+		ssrcTransaction.setMediaServerId(mediaServerId);
+
+		redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX +  deviceId + "_" + channelId, ssrcTransaction);
 	}
 	}
-	
-	public void put(String deviceId, String channelId ,String ssrc, String streamId, ClientTransaction transaction){
-		sessionMap.put(deviceId + "_" + channelId, transaction);
-		ssrcMap.put(deviceId + "_" + channelId, ssrc);
-		streamIdMap.put(deviceId + "_" + channelId, streamId);
+
+	public void put(String deviceId, String channelId , Dialog dialog){
+		SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
+		if (ssrcTransaction != null) {
+			byte[] dialogByteArray = SerializeUtils.serialize(dialog);
+			ssrcTransaction.setDialog(dialogByteArray);
+		}
+		redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX +  deviceId + "_" + channelId, ssrcTransaction);
 	}
 	}
+
 	
 	
 	public ClientTransaction getTransaction(String deviceId, String channelId){
 	public ClientTransaction getTransaction(String deviceId, String channelId){
-		return sessionMap.get(deviceId + "_" + channelId);
+		SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
+		if (ssrcTransaction == null) return null;
+		byte[] transactionByteArray = ssrcTransaction.getTransaction();
+		ClientTransaction clientTransaction = (ClientTransaction)SerializeUtils.deSerialize(transactionByteArray);
+		return clientTransaction;
 	}
 	}
 
 
-	public String getStreamId(String deviceId, String channelId){
-		return streamIdMap.get(deviceId + "_" + channelId);
+	public SIPDialog getDialog(String deviceId, String channelId){
+		SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
+		if (ssrcTransaction == null) return null;
+		byte[] dialogByteArray = ssrcTransaction.getDialog();
+		if (dialogByteArray == null) return null;
+		SIPDialog dialog = (SIPDialog)SerializeUtils.deSerialize(dialogByteArray);
+		return dialog;
 	}
 	}
-	
-	public void remove(String deviceId, String channelId) {
-		sessionMap.remove(deviceId + "_" + channelId);
-		if (ssrcMap.get(deviceId + "_" + channelId) != null) {
-			SsrcUtil.releaseSsrc(ssrcMap.get(deviceId + "_" + channelId));
-		}
-		ssrcMap.remove(deviceId + "_" + channelId);
-		streamIdMap.remove(deviceId + "_" + channelId);
+
+	public SsrcTransaction getSsrcTransaction(String deviceId, String channelId){
+		SsrcTransaction ssrcTransaction = (SsrcTransaction)redisUtil.get(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + deviceId + "_" + channelId);
+		return ssrcTransaction;
 	}
 	}
 
 
-	public ConcurrentHashMap<String, ClientTransaction> getSessionMap() {
-		return sessionMap;
+	public String getStreamId(String deviceId, String channelId){
+		SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
+		if (ssrcTransaction == null) return null;
+		return ssrcTransaction.getStreamId();
+	}
+	public String getMediaServerId(String deviceId, String channelId){
+		SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
+		if (ssrcTransaction == null) return null;
+		return ssrcTransaction.getMediaServerId();
 	}
 	}
 
 
-	public ConcurrentHashMap<String, String> getSsrcMap() {
-		return ssrcMap;
+	public String getSSRC(String deviceId, String channelId){
+		SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
+		if (ssrcTransaction == null) return null;
+		return ssrcTransaction.getSsrc();
+	}
+	
+	public void remove(String deviceId, String channelId) {
+		SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
+		if (ssrcTransaction == null) return;
+		redisUtil.del(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX +  deviceId + "_" + channelId);
 	}
 	}
 
 
-	public ConcurrentHashMap<String, String> getStreamIdMap() {
-		return streamIdMap;
+	public List<SsrcTransaction> getAllSsrc() {
+		List<Object> ssrcTransactionKeys = redisUtil.scan(String.format("%s_*_*", VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX));
+		List<SsrcTransaction> result= new ArrayList<>();
+		for (int i = 0; i < ssrcTransactionKeys.size(); i++) {
+			String key = (String)ssrcTransactionKeys.get(i);
+			SsrcTransaction ssrcTransaction = (SsrcTransaction)redisUtil.get(key);
+			result.add(ssrcTransaction);
+		}
+		return result;
 	}
 	}
 }
 }

+ 1 - 1
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java

@@ -7,6 +7,7 @@ import javax.sip.header.CSeqHeader;
 import javax.sip.message.Request;
 import javax.sip.message.Request;
 import javax.sip.message.Response;
 import javax.sip.message.Response;
 
 
+import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.service.IMediaServerService;
@@ -108,7 +109,6 @@ public class SIPProcessorFactory {
 	@Autowired
 	@Autowired
 	private IMediaServerService mediaServerService;
 	private IMediaServerService mediaServerService;
 
 
-
 	// 注:这里使用注解会导致循环依赖注入,暂用springBean
 	// 注:这里使用注解会导致循环依赖注入,暂用springBean
 	private SipProvider tcpSipProvider;
 	private SipProvider tcpSipProvider;
 		
 		

+ 4 - 6
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java

@@ -3,8 +3,8 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd;
 import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
+import com.genersoft.iot.vmp.service.bean.SSRCInfo;
 
 
 /**    
 /**    
  * @Description:设备能力接口,用于定义设备的控制、查询能力   
  * @Description:设备能力接口,用于定义设备的控制、查询能力   
@@ -92,7 +92,7 @@ public interface ISIPCommander {
 	 * @param device  视频设备
 	 * @param device  视频设备
 	 * @param channelId  预览通道
 	 * @param channelId  预览通道
 	 */
 	 */
-	void playStreamCmd(IMediaServerItem mediaServerItem, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
+	void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
 	
 	
 	/**
 	/**
 	 * 请求回放视频流
 	 * 请求回放视频流
@@ -102,7 +102,7 @@ public interface ISIPCommander {
 	 * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
 	 * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
 	 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
 	 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
 	 */
 	 */
-	void playbackStreamCmd(IMediaServerItem mediaServerItem,Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
+	void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInf, Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
 
 
 	/**
 	/**
 	 * 请求历史媒体下载
 	 * 请求历史媒体下载
@@ -113,12 +113,10 @@ public interface ISIPCommander {
 	 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
 	 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
 	 * @param downloadSpeed 下载倍速参数
 	 * @param downloadSpeed 下载倍速参数
 	 */ 
 	 */ 
-	void downloadStreamCmd(IMediaServerItem mediaServerItem,Device device, String channelId, String startTime, String endTime, String downloadSpeed, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
+	void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, String startTime, String endTime, String downloadSpeed, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
 
 
 	/**
 	/**
 	 * 视频流停止
 	 * 视频流停止
-	 * 
-	 * @param ssrc  ssrc
 	 */
 	 */
 	void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent);
 	void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent);
 	void streamByeCmd(String deviceId, String channelId);
 	void streamByeCmd(String deviceId, String channelId);

+ 89 - 122
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java

@@ -1,6 +1,8 @@
 package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
 package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
 
 
+import java.lang.reflect.Field;
 import java.text.ParseException;
 import java.text.ParseException;
+import java.util.HashSet;
 
 
 import javax.sip.*;
 import javax.sip.*;
 import javax.sip.address.SipURI;
 import javax.sip.address.SipURI;
@@ -8,18 +10,21 @@ import javax.sip.header.CallIdHeader;
 import javax.sip.header.ViaHeader;
 import javax.sip.header.ViaHeader;
 import javax.sip.message.Request;
 import javax.sip.message.Request;
 
 
-import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.JSONObject;
-import com.genersoft.iot.vmp.common.StreamInfo;
-import com.genersoft.iot.vmp.conf.MediaConfig;
 import com.genersoft.iot.vmp.conf.UserSetup;
 import com.genersoft.iot.vmp.conf.UserSetup;
+import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
 import com.genersoft.iot.vmp.media.zlm.*;
 import com.genersoft.iot.vmp.media.zlm.*;
 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
+import com.genersoft.iot.vmp.service.IMediaServerService;
+import com.genersoft.iot.vmp.service.bean.SSRCInfo;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
+import gov.nist.javax.sip.SipProviderImpl;
+import gov.nist.javax.sip.SipStackImpl;
 import gov.nist.javax.sip.message.SIPRequest;
 import gov.nist.javax.sip.message.SIPRequest;
+import gov.nist.javax.sip.stack.SIPDialog;
+import gov.nist.javax.sip.stack.SIPTransaction;
 import org.slf4j.Logger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -35,7 +40,6 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
 import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
 import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
 import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
 import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
-import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
 import org.springframework.util.StringUtils;
 import org.springframework.util.StringUtils;
 
 
 /**    
 /**    
@@ -55,12 +59,12 @@ public class SIPCommander implements ISIPCommander {
 	@Lazy
 	@Lazy
 	@Autowired
 	@Autowired
 	@Qualifier(value="tcpSipProvider")
 	@Qualifier(value="tcpSipProvider")
-	private SipProvider tcpSipProvider;
+	private SipProviderImpl tcpSipProvider;
 
 
 	@Lazy
 	@Lazy
 	@Autowired
 	@Autowired
 	@Qualifier(value="udpSipProvider")
 	@Qualifier(value="udpSipProvider")
-	private SipProvider udpSipProvider;
+	private SipProviderImpl udpSipProvider;
 
 
 	@Autowired
 	@Autowired
 	private SIPRequestHeaderProvider headerProvider;
 	private SIPRequestHeaderProvider headerProvider;
@@ -74,9 +78,6 @@ public class SIPCommander implements ISIPCommander {
 	@Autowired
 	@Autowired
 	private IRedisCatchStorage redisCatchStorage;
 	private IRedisCatchStorage redisCatchStorage;
 
 
-	@Autowired
-	private ZLMRTPServerFactory zlmrtpServerFactory;
-
 	@Autowired
 	@Autowired
 	private UserSetup userSetup;
 	private UserSetup userSetup;
 
 
@@ -86,6 +87,11 @@ public class SIPCommander implements ISIPCommander {
 	@Autowired
 	@Autowired
 	private SipSubscribe sipSubscribe;
 	private SipSubscribe sipSubscribe;
 
 
+	@Autowired
+	private IMediaServerService mediaServerService;
+
+	private SIPDialog dialog;
+
 	public SipConfig getSipConfig() {
 	public SipConfig getSipConfig() {
 		return sipConfig;
 		return sipConfig;
 	}
 	}
@@ -334,26 +340,13 @@ public class SIPCommander implements ISIPCommander {
 	  * @param errorEvent sip错误订阅
 	  * @param errorEvent sip错误订阅
 	  */
 	  */
 	@Override
 	@Override
-	public void playStreamCmd(IMediaServerItem mediaServerItem, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent) {
-		String streamId = null;
+	public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent) {
+		String streamId = ssrcInfo.getStreamId();
 		try {
 		try {
 			if (device == null) return;
 			if (device == null) return;
 			String streamMode = device.getStreamMode().toUpperCase();
 			String streamMode = device.getStreamMode().toUpperCase();
 
 
-			String ssrc = streamSession.createPlaySsrc();
-			if (mediaServerItem.isRtpEnable()) {
-				streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
-			}else {
-				streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
-			}
-			Integer mediaPort = null;
-			// 使用动态udp端口
-			if (mediaServerItem.isRtpEnable()) {
-				mediaPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId);
-			}else {
-				mediaPort = mediaServerItem.getRtpProxyPort();
-			}
-			logger.info("{} 分配的ZLM为: {} [{}:{}]", streamId, mediaServerItem.getId(), mediaServerItem.getIp(), mediaPort);
+			logger.info("{} 分配的ZLM为: {} [{}:{}]", streamId, mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
 			// 添加订阅
 			// 添加订阅
 			JSONObject subscribeKey = new JSONObject();
 			JSONObject subscribeKey = new JSONObject();
 			subscribeKey.put("app", "rtp");
 			subscribeKey.put("app", "rtp");
@@ -361,7 +354,7 @@ public class SIPCommander implements ISIPCommander {
 			subscribeKey.put("regist", true);
 			subscribeKey.put("regist", true);
 			subscribeKey.put("mediaServerId", mediaServerItem.getId());
 			subscribeKey.put("mediaServerId", mediaServerItem.getId());
 			subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
 			subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
-					(IMediaServerItem mediaServerItemInUse, JSONObject json)->{
+					(MediaServerItem mediaServerItemInUse, JSONObject json)->{
 				if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
 				if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
 				event.response(mediaServerItemInUse, json);
 				event.response(mediaServerItemInUse, json);
 				subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
 				subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
@@ -369,7 +362,6 @@ public class SIPCommander implements ISIPCommander {
 			//
 			//
 			StringBuffer content = new StringBuffer(200);
 			StringBuffer content = new StringBuffer(200);
 			content.append("v=0\r\n");
 			content.append("v=0\r\n");
-//			content.append("o=" + sipConfig.getSipId() + " 0 0 IN IP4 "+mediaInfo.getWanIp()+"\r\n");
 			content.append("o="+"00000"+" 0 0 IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");
 			content.append("o="+"00000"+" 0 0 IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");
 			content.append("s=Play\r\n");
 			content.append("s=Play\r\n");
 			content.append("c=IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");
 			content.append("c=IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");
@@ -377,11 +369,11 @@ public class SIPCommander implements ISIPCommander {
 
 
 			if (userSetup.isSeniorSdp()) {
 			if (userSetup.isSeniorSdp()) {
 				if("TCP-PASSIVE".equals(streamMode)) {
 				if("TCP-PASSIVE".equals(streamMode)) {
-					content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
+					content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
 				}else if ("TCP-ACTIVE".equals(streamMode)) {
 				}else if ("TCP-ACTIVE".equals(streamMode)) {
-					content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
+					content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
 				}else if("UDP".equals(streamMode)) {
 				}else if("UDP".equals(streamMode)) {
-					content.append("m=video "+ mediaPort +" RTP/AVP 96 126 125 99 34 98 97\r\n");
+					content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 126 125 99 34 98 97\r\n");
 				}
 				}
 				content.append("a=recvonly\r\n");
 				content.append("a=recvonly\r\n");
 				content.append("a=rtpmap:96 PS/90000\r\n");
 				content.append("a=rtpmap:96 PS/90000\r\n");
@@ -402,11 +394,11 @@ public class SIPCommander implements ISIPCommander {
 				}
 				}
 			}else {
 			}else {
 				if("TCP-PASSIVE".equals(streamMode)) {
 				if("TCP-PASSIVE".equals(streamMode)) {
-					content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 98 97\r\n");
+					content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n");
 				}else if ("TCP-ACTIVE".equals(streamMode)) {
 				}else if ("TCP-ACTIVE".equals(streamMode)) {
-					content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 98 97\r\n");
+					content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n");
 				}else if("UDP".equals(streamMode)) {
 				}else if("UDP".equals(streamMode)) {
-					content.append("m=video "+ mediaPort +" RTP/AVP 96 98 97\r\n");
+					content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 98 97\r\n");
 				}
 				}
 				content.append("a=recvonly\r\n");
 				content.append("a=recvonly\r\n");
 				content.append("a=rtpmap:96 PS/90000\r\n");
 				content.append("a=rtpmap:96 PS/90000\r\n");
@@ -421,20 +413,25 @@ public class SIPCommander implements ISIPCommander {
 				}
 				}
 			}
 			}
 
 
-			content.append("y="+ssrc+"\r\n");//ssrc
+			content.append("y="+ssrcInfo.getSsrc()+"\r\n");//ssrc
 
 
 			String tm = Long.toString(System.currentTimeMillis());
 			String tm = Long.toString(System.currentTimeMillis());
 
 
 			CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
 			CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
 					: udpSipProvider.getNewCallId();
 					: udpSipProvider.getNewCallId();
 
 
-			Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, "FromInvt" + tm, null, ssrc, callIdHeader);
+			Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, "FromInvt" + tm, null, ssrcInfo.getSsrc(), callIdHeader);
 
 
-			ClientTransaction transaction = transmitRequest(device, request, (e -> {
+			String finalStreamId = streamId;
+			transmitRequest(device, request, (e -> {
 				streamSession.remove(device.getDeviceId(), channelId);
 				streamSession.remove(device.getDeviceId(), channelId);
+				mediaServerService.releaseSsrc(mediaServerItem, ssrcInfo.getSsrc());
 				errorEvent.response(e);
 				errorEvent.response(e);
-			}));
-			streamSession.put(device.getDeviceId(), channelId ,ssrc,streamId, transaction);
+			}), e ->{
+				streamSession.put(device.getDeviceId(), channelId ,ssrcInfo.getSsrc(), finalStreamId, mediaServerItem.getId(),e.getClientTransaction());
+				streamSession.put(device.getDeviceId(), channelId , e.getDialog());
+			});
+
 			
 			
 		} catch ( SipException | ParseException | InvalidArgumentException e) {
 		} catch ( SipException | ParseException | InvalidArgumentException e) {
 			e.printStackTrace();
 			e.printStackTrace();
@@ -450,30 +447,21 @@ public class SIPCommander implements ISIPCommander {
 	 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
 	 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
 	 */ 
 	 */ 
 	@Override
 	@Override
-	public void playbackStreamCmd(IMediaServerItem mediaServerItem,Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event
+	public void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event
 			, SipSubscribe.Event errorEvent) {
 			, SipSubscribe.Event errorEvent) {
 		try {
 		try {
-			String ssrc = streamSession.createPlayBackSsrc();
-			String streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
 
 
-			Integer mediaPort = null;
-			// 使用动态udp端口
-			if (mediaServerItem.isRtpEnable()) {
-				mediaPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId);
-			}else {
-				mediaPort = mediaServerItem.getRtpProxyPort();
-			}
-			logger.info("{} 分配的ZLM为: {} [{}:{}]", streamId, mediaServerItem.getId(), mediaServerItem.getIp(), mediaPort);
+			logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStreamId(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
 
 
 			// 添加订阅
 			// 添加订阅
 			JSONObject subscribeKey = new JSONObject();
 			JSONObject subscribeKey = new JSONObject();
 			subscribeKey.put("app", "rtp");
 			subscribeKey.put("app", "rtp");
-			subscribeKey.put("stream", streamId);
+			subscribeKey.put("stream", ssrcInfo.getStreamId());
 			subscribeKey.put("regist", true);
 			subscribeKey.put("regist", true);
 			subscribeKey.put("mediaServerId", mediaServerItem.getId());
 			subscribeKey.put("mediaServerId", mediaServerItem.getId());
 			logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString());
 			logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString());
 			subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
 			subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
-					(IMediaServerItem mediaServerItemInUse, JSONObject json)->{
+					(MediaServerItem mediaServerItemInUse, JSONObject json)->{
 				if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
 				if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
 				event.response(mediaServerItemInUse, json);
 				event.response(mediaServerItemInUse, json);
 				subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
 				subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
@@ -494,11 +482,11 @@ public class SIPCommander implements ISIPCommander {
 
 
 			if (userSetup.isSeniorSdp()) {
 			if (userSetup.isSeniorSdp()) {
 				if("TCP-PASSIVE".equals(streamMode)) {
 				if("TCP-PASSIVE".equals(streamMode)) {
-					content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
+					content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
 				}else if ("TCP-ACTIVE".equals(streamMode)) {
 				}else if ("TCP-ACTIVE".equals(streamMode)) {
-					content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
+					content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
 				}else if("UDP".equals(streamMode)) {
 				}else if("UDP".equals(streamMode)) {
-					content.append("m=video "+ mediaPort +" RTP/AVP 96 126 125 99 34 98 97\r\n");
+					content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 126 125 99 34 98 97\r\n");
 				}
 				}
 				content.append("a=recvonly\r\n");
 				content.append("a=recvonly\r\n");
 				content.append("a=rtpmap:96 PS/90000\r\n");
 				content.append("a=rtpmap:96 PS/90000\r\n");
@@ -519,11 +507,11 @@ public class SIPCommander implements ISIPCommander {
 				}
 				}
 			}else {
 			}else {
 				if("TCP-PASSIVE".equals(streamMode)) {
 				if("TCP-PASSIVE".equals(streamMode)) {
-					content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 98 97\r\n");
+					content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n");
 				}else if ("TCP-ACTIVE".equals(streamMode)) {
 				}else if ("TCP-ACTIVE".equals(streamMode)) {
-					content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 98 97\r\n");
+					content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n");
 				}else if("UDP".equals(streamMode)) {
 				}else if("UDP".equals(streamMode)) {
-					content.append("m=video "+ mediaPort +" RTP/AVP 96 98 97\r\n");
+					content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 98 97\r\n");
 				}
 				}
 				content.append("a=recvonly\r\n");
 				content.append("a=recvonly\r\n");
 				content.append("a=rtpmap:96 PS/90000\r\n");
 				content.append("a=rtpmap:96 PS/90000\r\n");
@@ -538,7 +526,7 @@ public class SIPCommander implements ISIPCommander {
 				}
 				}
 			}
 			}
 
 
-	        content.append("y="+ssrc+"\r\n");//ssrc
+	        content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
 	        
 	        
 			String tm = Long.toString(System.currentTimeMillis());
 			String tm = Long.toString(System.currentTimeMillis());
 
 
@@ -547,9 +535,11 @@ public class SIPCommander implements ISIPCommander {
 
 
 	        Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader);
 	        Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader);
 
 
-	        ClientTransaction transaction = transmitRequest(device, request, errorEvent);
-	        streamSession.put(device.getDeviceId(), channelId, ssrc, streamId, transaction);
-
+	        transmitRequest(device, request, errorEvent, okEvent -> {
+				Dialog dialog = okEvent.getClientTransaction().getDialog();
+	        	streamSession.put(device.getDeviceId(), channelId, ssrcInfo.getSsrc(), ssrcInfo.getStreamId(), mediaServerItem.getId(), okEvent.getClientTransaction());
+				streamSession.put(device.getDeviceId(), channelId, dialog);
+			});
 		} catch ( SipException | ParseException | InvalidArgumentException e) {
 		} catch ( SipException | ParseException | InvalidArgumentException e) {
 			e.printStackTrace();
 			e.printStackTrace();
 		}
 		}
@@ -565,30 +555,20 @@ public class SIPCommander implements ISIPCommander {
 	 * @param downloadSpeed 下载倍速参数
 	 * @param downloadSpeed 下载倍速参数
 	 */ 
 	 */ 
 	@Override
 	@Override
-	public void downloadStreamCmd(IMediaServerItem mediaServerItem,Device device, String channelId, String startTime, String endTime, String downloadSpeed, ZLMHttpHookSubscribe.Event event
+	public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, String startTime, String endTime, String downloadSpeed, ZLMHttpHookSubscribe.Event event
 			, SipSubscribe.Event errorEvent) {
 			, SipSubscribe.Event errorEvent) {
 		try {
 		try {
-			String ssrc = streamSession.createPlayBackSsrc();
-			String streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
-
-			Integer mediaPort = null;
-			// 使用动态udp端口
-			if (mediaServerItem.isRtpEnable()) {
-				mediaPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId);
-			}else {
-				mediaPort = mediaServerItem.getRtpProxyPort();
-			}
-			logger.info("{} 分配的ZLM为: {} [{}:{}]", streamId, mediaServerItem.getId(), mediaServerItem.getIp(), mediaPort);
+			logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStreamId(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
 
 
 			// 添加订阅
 			// 添加订阅
 			JSONObject subscribeKey = new JSONObject();
 			JSONObject subscribeKey = new JSONObject();
 			subscribeKey.put("app", "rtp");
 			subscribeKey.put("app", "rtp");
-			subscribeKey.put("stream", streamId);
+			subscribeKey.put("stream", ssrcInfo.getStreamId());
 			subscribeKey.put("regist", true);
 			subscribeKey.put("regist", true);
 			subscribeKey.put("mediaServerId", mediaServerItem.getId());
 			subscribeKey.put("mediaServerId", mediaServerItem.getId());
 			logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString());
 			logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString());
 			subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
 			subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
-					(IMediaServerItem mediaServerItemInUse, JSONObject json)->{
+					(MediaServerItem mediaServerItemInUse, JSONObject json)->{
 				if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
 				if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
 				event.response(mediaServerItemInUse, json);
 				event.response(mediaServerItemInUse, json);
 				subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
 				subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
@@ -609,11 +589,11 @@ public class SIPCommander implements ISIPCommander {
 
 
 			if (userSetup.isSeniorSdp()) {
 			if (userSetup.isSeniorSdp()) {
 				if("TCP-PASSIVE".equals(streamMode)) {
 				if("TCP-PASSIVE".equals(streamMode)) {
-					content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
+					content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
 				}else if ("TCP-ACTIVE".equals(streamMode)) {
 				}else if ("TCP-ACTIVE".equals(streamMode)) {
-					content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
+					content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
 				}else if("UDP".equals(streamMode)) {
 				}else if("UDP".equals(streamMode)) {
-					content.append("m=video "+ mediaPort +" RTP/AVP 96 126 125 99 34 98 97\r\n");
+					content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 126 125 99 34 98 97\r\n");
 				}
 				}
 				content.append("a=recvonly\r\n");
 				content.append("a=recvonly\r\n");
 				content.append("a=rtpmap:96 PS/90000\r\n");
 				content.append("a=rtpmap:96 PS/90000\r\n");
@@ -634,11 +614,11 @@ public class SIPCommander implements ISIPCommander {
 				}
 				}
 			}else {
 			}else {
 				if("TCP-PASSIVE".equals(streamMode)) {
 				if("TCP-PASSIVE".equals(streamMode)) {
-					content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 98 97\r\n");
+					content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n");
 				}else if ("TCP-ACTIVE".equals(streamMode)) {
 				}else if ("TCP-ACTIVE".equals(streamMode)) {
-					content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 98 97\r\n");
+					content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n");
 				}else if("UDP".equals(streamMode)) {
 				}else if("UDP".equals(streamMode)) {
-					content.append("m=video "+ mediaPort +" RTP/AVP 96 98 97\r\n");
+					content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 98 97\r\n");
 				}
 				}
 				content.append("a=recvonly\r\n");
 				content.append("a=recvonly\r\n");
 				content.append("a=rtpmap:96 PS/90000\r\n");
 				content.append("a=rtpmap:96 PS/90000\r\n");
@@ -654,7 +634,7 @@ public class SIPCommander implements ISIPCommander {
 			}
 			}
 			content.append("a=downloadspeed:" + downloadSpeed + "\r\n");
 			content.append("a=downloadspeed:" + downloadSpeed + "\r\n");
 
 
-	        content.append("y="+ssrc+"\r\n");//ssrc
+	        content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
 	        
 	        
 			String tm = Long.toString(System.currentTimeMillis());
 			String tm = Long.toString(System.currentTimeMillis());
 
 
@@ -664,7 +644,7 @@ public class SIPCommander implements ISIPCommander {
 	        Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader);
 	        Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader);
 
 
 	        ClientTransaction transaction = transmitRequest(device, request, errorEvent);
 	        ClientTransaction transaction = transmitRequest(device, request, errorEvent);
-	        streamSession.put(device.getDeviceId(), channelId, ssrc, streamId, transaction);
+	        streamSession.put(device.getDeviceId(), channelId, ssrcInfo.getSsrc(), ssrcInfo.getStreamId(), mediaServerItem.getId(), transaction);
 
 
 		} catch ( SipException | ParseException | InvalidArgumentException e) {
 		} catch ( SipException | ParseException | InvalidArgumentException e) {
 			e.printStackTrace();
 			e.printStackTrace();
@@ -684,53 +664,35 @@ public class SIPCommander implements ISIPCommander {
 	 */
 	 */
 	@Override
 	@Override
 	public void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent) {
 	public void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent) {
-		StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
 		try {
 		try {
 			ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId);
 			ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId);
-			// 服务重启后, 无法直接发送bye, 通过手动构建发送
-//			if (transaction == null) {
-//
-//				if (streamInfo != null) {
-//					MediaServerItem mediaServerItem = redisCatchStorage.getMediaInfo(streamInfo.getMediaServerId());
-//					JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaServerItem,streamInfo.getApp(), streamInfo.getStreamId());
-//					if (mediaList != null) { // 仍在推流才发送
-//						if (mediaList.getInteger("code") == 0) {
-//							JSONArray data = mediaList.getJSONArray("data");
-//							if (data != null && data.size() > 0) {
-//								Device device = storager.queryVideoDevice(deviceId);
-//								if (device != null) {
-//									StreamInfo.TransactionInfo transactionInfo = streamInfo.getTransactionInfo();
-//									try {
-//										Request byteRequest = headerProvider.createByteRequest(device, channelId,
-//												transactionInfo.branch,
-//												transactionInfo.localTag,
-//												transactionInfo.remoteTag,
-//												transactionInfo.callId);
-//										transmitRequest(device, byteRequest);
-//									} catch (InvalidArgumentException e) {
-//										e.printStackTrace();
-//									}
-//								}
-//							}
-//						}
-//					}
-//					redisCatchStorage.stopPlay(streamInfo);
-//				}
-//
-//				if (okEvent != null) {
-//					okEvent.response(null);
-//				}
-//				return;
-//			}
 			if (transaction == null) {
 			if (transaction == null) {
 				logger.warn("[ {} -> {}]停止视频流的时候发现事务已丢失", deviceId, channelId);
 				logger.warn("[ {} -> {}]停止视频流的时候发现事务已丢失", deviceId, channelId);
 				return;
 				return;
 			}
 			}
-			Dialog dialog = transaction.getDialog();
+			SIPDialog dialog = streamSession.getDialog(deviceId, channelId);
 			if (dialog == null) {
 			if (dialog == null) {
 				logger.warn("[ {} -> {}]停止视频流的时候发现对话已丢失", deviceId, channelId);
 				logger.warn("[ {} -> {}]停止视频流的时候发现对话已丢失", deviceId, channelId);
 				return;
 				return;
 			}
 			}
+			SipStack sipStack = udpSipProvider.getSipStack();
+			SIPDialog sipDialog = ((SipStackImpl) sipStack).putDialog(dialog);
+			if (dialog != sipDialog) {
+				dialog = sipDialog;
+			}else {
+				dialog.setSipProvider(udpSipProvider);
+				try {
+					Field sipStackField = SIPDialog.class.getDeclaredField("sipStack");
+					sipStackField.setAccessible(true);
+					sipStackField.set(dialog, sipStack);
+					Field eventListenersField = SIPDialog.class.getDeclaredField("eventListeners");
+					eventListenersField.setAccessible(true);
+					eventListenersField.set(dialog, new HashSet<>());
+				} catch (NoSuchFieldException | IllegalAccessException e) {
+					e.printStackTrace();
+				}
+			}
+
 			Request byeRequest = dialog.createRequest(Request.BYE);
 			Request byeRequest = dialog.createRequest(Request.BYE);
 			SipURI byeURI = (SipURI) byeRequest.getRequestURI();
 			SipURI byeURI = (SipURI) byeRequest.getRequestURI();
 			SIPRequest request = (SIPRequest)transaction.getRequest();
 			SIPRequest request = (SIPRequest)transaction.getRequest();
@@ -752,7 +714,12 @@ public class SIPCommander implements ISIPCommander {
 
 
 			dialog.sendRequest(clientTransaction);
 			dialog.sendRequest(clientTransaction);
 
 
-			streamSession.remove(deviceId, channelId);
+			SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(deviceId, channelId);
+			if (ssrcTransaction != null) {
+				MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransaction.getMediaServerId());
+				mediaServerService.releaseSsrc(mediaServerItem, ssrcTransaction.getSsrc());
+				streamSession.remove(deviceId, channelId);
+			}
 		} catch (SipException | ParseException e) {
 		} catch (SipException | ParseException e) {
 			e.printStackTrace();
 			e.printStackTrace();
 		}
 		}

+ 1 - 2
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java

@@ -13,7 +13,6 @@ import com.genersoft.iot.vmp.common.StreamInfo;
 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
 import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
 import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@@ -81,7 +80,7 @@ public class AckRequestProcessor extends SIPRequestAbstractProcessor {
 			while (!rtpPushed) {
 			while (!rtpPushed) {
 				try {
 				try {
 					if (System.currentTimeMillis() - startTime < 30 * 1000) {
 					if (System.currentTimeMillis() - startTime < 30 * 1000) {
-						IMediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
+						MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
 						if (zlmrtpServerFactory.isStreamReady(mediaInfo, streamInfo.getApp(), streamInfo.getStreamId())) {
 						if (zlmrtpServerFactory.isStreamReady(mediaInfo, streamInfo.getApp(), streamInfo.getStreamId())) {
 							rtpPushed = true;
 							rtpPushed = true;
 							logger.info("已获取设备推流[{}/{}],开始向上级推流[{}:{}]",
 							logger.info("已获取设备推流[{}/{}],开始向上级推流[{}:{}]",

+ 1 - 2
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;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
 import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
 import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@@ -65,7 +64,7 @@ public class ByeRequestProcessor extends SIPRequestAbstractProcessor {
 				param.put("stream",streamId);
 				param.put("stream",streamId);
 				param.put("ssrc",sendRtpItem.getSsrc());
 				param.put("ssrc",sendRtpItem.getSsrc());
 				logger.info("停止向上级推流:" + streamId);
 				logger.info("停止向上级推流:" + streamId);
-				IMediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
+				MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
 				zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
 				zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
 				redisCatchStorage.deleteSendRTPServer(platformGbId, channelId);
 				redisCatchStorage.deleteSendRTPServer(platformGbId, channelId);
 				if (zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId) == 0) {
 				if (zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId) == 0) {

+ 1 - 4
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java

@@ -11,14 +11,11 @@ import javax.sip.header.*;
 import javax.sip.message.Request;
 import javax.sip.message.Request;
 import javax.sip.message.Response;
 import javax.sip.message.Response;
 
 
-import com.genersoft.iot.vmp.common.StreamInfo;
-import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
 import com.genersoft.iot.vmp.gb28181.bean.*;
 import com.genersoft.iot.vmp.gb28181.bean.*;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
 import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
 import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@@ -97,7 +94,7 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
 				// 查询平台下是否有该通道
 				// 查询平台下是否有该通道
 				DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId);
 				DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId);
 				GbStream gbStream = storager.queryStreamInParentPlatform(requesterId, channelId);
 				GbStream gbStream = storager.queryStreamInParentPlatform(requesterId, channelId);
-				IMediaServerItem mediaServerItem = null;
+				MediaServerItem mediaServerItem = null;
 				// 不是通道可能是直播流
 				// 不是通道可能是直播流
 				if (channel != null && gbStream == null ) {
 				if (channel != null && gbStream == null ) {
 					if (channel.getStatus() == 0) {
 					if (channel.getStatus() == 0) {

+ 13 - 1
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;
 import java.text.ParseException;
 import java.text.ParseException;
 
 
 import javax.sip.*;
 import javax.sip.*;
+import javax.sip.address.Address;
 import javax.sip.address.SipURI;
 import javax.sip.address.SipURI;
 import javax.sip.header.CSeqHeader;
 import javax.sip.header.CSeqHeader;
 import javax.sip.message.Request;
 import javax.sip.message.Request;
 import javax.sip.message.Response;
 import javax.sip.message.Response;
 
 
+import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
 import gov.nist.javax.sip.ResponseEventExt;
 import gov.nist.javax.sip.ResponseEventExt;
+import gov.nist.javax.sip.stack.SIPDialog;
 import org.slf4j.Logger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
 
 
 import com.genersoft.iot.vmp.conf.SipConfig;
 import com.genersoft.iot.vmp.conf.SipConfig;
@@ -28,6 +32,9 @@ public class InviteResponseProcessor implements ISIPResponseProcessor {
 
 
 	 private final static Logger logger = LoggerFactory.getLogger(InviteResponseProcessor.class);
 	 private final static Logger logger = LoggerFactory.getLogger(InviteResponseProcessor.class);
 
 
+	@Autowired
+	private VideoStreamSessionManager streamSession;
+
 	/**
 	/**
 	 * 处理invite响应
 	 * 处理invite响应
 	 * 
 	 * 
@@ -46,7 +53,7 @@ public class InviteResponseProcessor implements ISIPResponseProcessor {
 			// 下发ack
 			// 下发ack
 			if (statusCode == Response.OK) {
 			if (statusCode == Response.OK) {
 				ResponseEventExt event = (ResponseEventExt)evt;
 				ResponseEventExt event = (ResponseEventExt)evt;
-				Dialog dialog = evt.getDialog();
+				SIPDialog dialog = (SIPDialog)evt.getDialog();
 				CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
 				CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
 				Request reqAck = dialog.createAck(cseq.getSeqNumber());
 				Request reqAck = dialog.createAck(cseq.getSeqNumber());
 				SipURI requestURI = (SipURI) reqAck.getRequestURI();
 				SipURI requestURI = (SipURI) reqAck.getRequestURI();
@@ -54,7 +61,12 @@ public class InviteResponseProcessor implements ISIPResponseProcessor {
 				requestURI.setPort(event.getRemotePort());
 				requestURI.setPort(event.getRemotePort());
 				reqAck.setRequestURI(requestURI);
 				reqAck.setRequestURI(requestURI);
 				logger.info("向 " + event.getRemoteIpAddress() + ":" + event.getRemotePort() + "回复ack");
 				logger.info("向 " + event.getRemoteIpAddress() + ":" + event.getRemotePort() + "回复ack");
+				SipURI sipURI = (SipURI)dialog.getRemoteParty().getURI();
+				String deviceId = requestURI.getUser();
+				String channelId = sipURI.getUser();
+
 				dialog.sendAck(reqAck);
 				dialog.sendAck(reqAck);
+
 			}
 			}
 		} catch (InvalidArgumentException | SipException e) {
 		} catch (InvalidArgumentException | SipException e) {
 			e.printStackTrace();
 			e.printStackTrace();

+ 14 - 10
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java

@@ -3,15 +3,14 @@ package com.genersoft.iot.vmp.media.zlm;
 import java.util.List;
 import java.util.List;
 import java.util.UUID;
 import java.util.UUID;
 
 
-import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONArray;
 import com.genersoft.iot.vmp.common.StreamInfo;
 import com.genersoft.iot.vmp.common.StreamInfo;
 import com.genersoft.iot.vmp.conf.MediaConfig;
 import com.genersoft.iot.vmp.conf.MediaConfig;
 import com.genersoft.iot.vmp.conf.UserSetup;
 import com.genersoft.iot.vmp.conf.UserSetup;
 import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.gb28181.bean.Device;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.service.IMediaServerService;
+import com.genersoft.iot.vmp.service.bean.SSRCInfo;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
 import com.genersoft.iot.vmp.service.IPlayService;
 import com.genersoft.iot.vmp.service.IPlayService;
@@ -42,7 +41,6 @@ public class ZLMHttpHookListener {
 
 
 	private final static Logger logger = LoggerFactory.getLogger(ZLMHttpHookListener.class);
 	private final static Logger logger = LoggerFactory.getLogger(ZLMHttpHookListener.class);
 
 
-
 	@Autowired
 	@Autowired
 	private SIPCommander cmder;
 	private SIPCommander cmder;
 
 
@@ -125,7 +123,7 @@ public class ZLMHttpHookListener {
 		String mediaServerId = json.getString("mediaServerId");
 		String mediaServerId = json.getString("mediaServerId");
 		ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_play, json);
 		ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_play, json);
 		if (subscribe != null ) {
 		if (subscribe != null ) {
-			IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
+			MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
 			if (mediaInfo != null) {
 			if (mediaInfo != null) {
 				subscribe.response(mediaInfo, json);
 				subscribe.response(mediaInfo, json);
 			}
 			}
@@ -150,7 +148,7 @@ public class ZLMHttpHookListener {
 		String mediaServerId = json.getString("mediaServerId");
 		String mediaServerId = json.getString("mediaServerId");
 		ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_publish, json);
 		ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_publish, json);
 		if (subscribe != null) {
 		if (subscribe != null) {
-			IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
+			MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
 			if (mediaInfo != null) {
 			if (mediaInfo != null) {
 				subscribe.response(mediaInfo, json);
 				subscribe.response(mediaInfo, json);
 			}
 			}
@@ -237,7 +235,7 @@ public class ZLMHttpHookListener {
 		String mediaServerId = json.getString("mediaServerId");
 		String mediaServerId = json.getString("mediaServerId");
 		ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_shell_login, json);
 		ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_shell_login, json);
 		if (subscribe != null ) {
 		if (subscribe != null ) {
-			IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
+			MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
 			if (mediaInfo != null) {
 			if (mediaInfo != null) {
 				subscribe.response(mediaInfo, json);
 				subscribe.response(mediaInfo, json);
 			}
 			}
@@ -264,7 +262,7 @@ public class ZLMHttpHookListener {
 		String mediaServerId = json.getString("mediaServerId");
 		String mediaServerId = json.getString("mediaServerId");
 		ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, json);
 		ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, json);
 		if (subscribe != null ) {
 		if (subscribe != null ) {
-			IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
+			MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
 			if (mediaInfo != null) {
 			if (mediaInfo != null) {
 				subscribe.response(mediaInfo, json);
 				subscribe.response(mediaInfo, json);
 			}
 			}
@@ -297,7 +295,7 @@ public class ZLMHttpHookListener {
 				}
 				}
 			}else {
 			}else {
 				if (!"rtp".equals(app) ){
 				if (!"rtp".equals(app) ){
-					IMediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
+					MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
 					if (regist) {
 					if (regist) {
 						zlmMediaListManager.addMedia(mediaServerItem, app, streamId);
 						zlmMediaListManager.addMedia(mediaServerItem, app, streamId);
 					}else {
 					}else {
@@ -369,7 +367,7 @@ public class ZLMHttpHookListener {
 			logger.debug("ZLM HOOK on_stream_not_found API调用,参数:" + json.toString());
 			logger.debug("ZLM HOOK on_stream_not_found API调用,参数:" + json.toString());
 		}
 		}
 		String mediaServerId = json.getString("mediaServerId");
 		String mediaServerId = json.getString("mediaServerId");
-		IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
+		MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
 		if (userSetup.isAutoApplyPlay() && mediaInfo != null) {
 		if (userSetup.isAutoApplyPlay() && mediaInfo != null) {
 			String app = json.getString("app");
 			String app = json.getString("app");
 			String streamId = json.getString("stream");
 			String streamId = json.getString("stream");
@@ -381,7 +379,13 @@ public class ZLMHttpHookListener {
 					Device device = storager.queryVideoDevice(deviceId);
 					Device device = storager.queryVideoDevice(deviceId);
 					if (device != null) {
 					if (device != null) {
 						UUID uuid = UUID.randomUUID();
 						UUID uuid = UUID.randomUUID();
-						cmder.playStreamCmd(mediaInfo, device, channelId, (IMediaServerItem mediaServerItemInuse, JSONObject response) -> {
+						SSRCInfo ssrcInfo;
+						String streamId2 = null;
+						if (mediaInfo.isRtpEnable()) {
+							streamId2 = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
+						}
+						ssrcInfo = mediaServerService.openRTPServer(mediaInfo, streamId2);
+						cmder.playStreamCmd(mediaInfo, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> {
 							logger.info("收到订阅消息: " + response.toJSONString());
 							logger.info("收到订阅消息: " + response.toJSONString());
 							playService.onPublishHandlerForPlay(mediaServerItemInuse, response, deviceId, channelId, uuid.toString());
 							playService.onPublishHandlerForPlay(mediaServerItemInuse, response, deviceId, channelId, uuid.toString());
 						}, null);
 						}, null);

+ 5 - 3
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java

@@ -1,7 +1,6 @@
 package com.genersoft.iot.vmp.media.zlm;
 package com.genersoft.iot.vmp.media.zlm;
 
 
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.JSONObject;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
 
 
@@ -32,7 +31,7 @@ public class ZLMHttpHookSubscribe {
     }
     }
 
 
     public interface Event{
     public interface Event{
-        void response(IMediaServerItem mediaServerItem, JSONObject response);
+        void response(MediaServerItem mediaServerItem, JSONObject response);
     }
     }
 
 
     private Map<HookType, Map<JSONObject, ZLMHttpHookSubscribe.Event>> allSubscribes = new ConcurrentHashMap<>();
     private Map<HookType, Map<JSONObject, ZLMHttpHookSubscribe.Event>> allSubscribes = new ConcurrentHashMap<>();
@@ -58,6 +57,9 @@ public class ZLMHttpHookSubscribe {
                 if (result == null) {
                 if (result == null) {
                     result = key.getString(s).equals(hookResponse.getString(s));
                     result = key.getString(s).equals(hookResponse.getString(s));
                 }else {
                 }else {
+                    if (key.getString(s) == null) {
+                        continue;
+                    }
                     result = result && key.getString(s).equals(hookResponse.getString(s));
                     result = result && key.getString(s).equals(hookResponse.getString(s));
                 }
                 }
 
 
@@ -83,9 +85,9 @@ public class ZLMHttpHookSubscribe {
                 if (result == null) {
                 if (result == null) {
                     result = key.getString(s).equals(hookResponse.getString(s));
                     result = key.getString(s).equals(hookResponse.getString(s));
                 }else {
                 }else {
+                    if (key.getString(s) == null) continue;
                     result = result && key.getString(s).equals(hookResponse.getString(s));
                     result = result && key.getString(s).equals(hookResponse.getString(s));
                 }
                 }
-
             }
             }
             if (null != result && result){
             if (null != result && result){
                 iterator.remove();
                 iterator.remove();

+ 3 - 6
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java

@@ -1,12 +1,9 @@
 package com.genersoft.iot.vmp.media.zlm;
 package com.genersoft.iot.vmp.media.zlm;
 
 
-import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.JSONObject;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
-import com.genersoft.iot.vmp.gb28181.bean.GbStream;
 import com.genersoft.iot.vmp.service.IStreamPushService;
 import com.genersoft.iot.vmp.service.IStreamPushService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
@@ -76,7 +73,7 @@ public class ZLMMediaListManager {
                     jsonObject.put("stream", streamPushItem.getStream());
                     jsonObject.put("stream", streamPushItem.getStream());
                     jsonObject.put("mediaServerId", mediaServerItem.getId());
                     jsonObject.put("mediaServerId", mediaServerItem.getId());
                     subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_play,jsonObject,
                     subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_play,jsonObject,
-                            (IMediaServerItem mediaServerItemInuse, JSONObject response)->{
+                            (MediaServerItem mediaServerItemInuse, JSONObject response)->{
                                 updateMedia(mediaServerItem, response.getString("app"), response.getString("stream"));
                                 updateMedia(mediaServerItem, response.getString("app"), response.getString("stream"));
                             }
                             }
                     );
                     );
@@ -86,13 +83,13 @@ public class ZLMMediaListManager {
 
 
     }
     }
 
 
-    public void addMedia(IMediaServerItem mediaServerItem, String app, String streamId) {
+    public void addMedia(MediaServerItem mediaServerItem, String app, String streamId) {
         //使用异步更新推流
         //使用异步更新推流
         updateMedia(mediaServerItem, app, streamId);
         updateMedia(mediaServerItem, app, streamId);
     }
     }
 
 
 
 
-    public void updateMedia(IMediaServerItem mediaServerItem, String app, String streamId) {
+    public void updateMedia(MediaServerItem mediaServerItem, String app, String streamId) {
         //使用异步更新推流
         //使用异步更新推流
         zlmresTfulUtils.getMediaList(mediaServerItem, app, streamId, "rtmp", json->{
         zlmresTfulUtils.getMediaList(mediaServerItem, app, streamId, "rtmp", json->{
 
 

+ 21 - 24
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java

@@ -2,14 +2,11 @@ package com.genersoft.iot.vmp.media.zlm;
 
 
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.JSONObject;
-import com.genersoft.iot.vmp.conf.MediaConfig;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import okhttp3.*;
 import okhttp3.*;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.NotNull;
 import org.slf4j.Logger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
 
 
 import java.io.*;
 import java.io.*;
@@ -27,7 +24,7 @@ public class ZLMRESTfulUtils {
         void run(JSONObject response);
         void run(JSONObject response);
     }
     }
 
 
-    public JSONObject sendPost(IMediaServerItem mediaServerItem, String api, Map<String, Object> param, RequestCallback callback) {
+    public JSONObject sendPost(MediaServerItem mediaServerItem, String api, Map<String, Object> param, RequestCallback callback) {
         OkHttpClient client = new OkHttpClient();
         OkHttpClient client = new OkHttpClient();
         String url = String.format("http://%s:%s/index/api/%s",  mediaServerItem.getIp(), mediaServerItem.getHttpPort(), api);
         String url = String.format("http://%s:%s/index/api/%s",  mediaServerItem.getIp(), mediaServerItem.getHttpPort(), api);
         JSONObject responseJSON = null;
         JSONObject responseJSON = null;
@@ -93,7 +90,7 @@ public class ZLMRESTfulUtils {
     }
     }
 
 
 
 
-    public void sendPostForImg(IMediaServerItem mediaServerItem, String api, Map<String, Object> param, String targetPath, String fileName) {
+    public void sendPostForImg(MediaServerItem mediaServerItem, String api, Map<String, Object> param, String targetPath, String fileName) {
         OkHttpClient client = new OkHttpClient();
         OkHttpClient client = new OkHttpClient();
         String url = String.format("http://%s:%s/index/api/%s",  mediaServerItem.getIp(), mediaServerItem.getHttpPort(), api);
         String url = String.format("http://%s:%s/index/api/%s",  mediaServerItem.getIp(), mediaServerItem.getHttpPort(), api);
         JSONObject responseJSON = null;
         JSONObject responseJSON = null;
@@ -139,7 +136,7 @@ public class ZLMRESTfulUtils {
     }
     }
 
 
 
 
-    public JSONObject getMediaList(IMediaServerItem mediaServerItem,String app, String stream, String schema, RequestCallback callback){
+    public JSONObject getMediaList(MediaServerItem mediaServerItem, String app, String stream, String schema, RequestCallback callback){
         Map<String, Object> param = new HashMap<>();
         Map<String, Object> param = new HashMap<>();
         if (app != null) param.put("app",app);
         if (app != null) param.put("app",app);
         if (stream != null) param.put("stream",stream);
         if (stream != null) param.put("stream",stream);
@@ -148,15 +145,15 @@ public class ZLMRESTfulUtils {
         return sendPost(mediaServerItem, "getMediaList",param, callback);
         return sendPost(mediaServerItem, "getMediaList",param, callback);
     }
     }
 
 
-    public JSONObject getMediaList(IMediaServerItem mediaServerItem,String app, String stream){
+    public JSONObject getMediaList(MediaServerItem mediaServerItem, String app, String stream){
         return getMediaList(mediaServerItem, app, stream,null,  null);
         return getMediaList(mediaServerItem, app, stream,null,  null);
     }
     }
 
 
-    public JSONObject getMediaList(IMediaServerItem mediaServerItem,RequestCallback callback){
+    public JSONObject getMediaList(MediaServerItem mediaServerItem, RequestCallback callback){
         return sendPost(mediaServerItem, "getMediaList",null, callback);
         return sendPost(mediaServerItem, "getMediaList",null, callback);
     }
     }
 
 
-    public JSONObject getMediaInfo(IMediaServerItem mediaServerItem,String app, String schema, String stream){
+    public JSONObject getMediaInfo(MediaServerItem mediaServerItem, String app, String schema, String stream){
         Map<String, Object> param = new HashMap<>();
         Map<String, Object> param = new HashMap<>();
         param.put("app",app);
         param.put("app",app);
         param.put("schema",schema);
         param.put("schema",schema);
@@ -165,13 +162,13 @@ public class ZLMRESTfulUtils {
         return sendPost(mediaServerItem, "getMediaInfo",param, null);
         return sendPost(mediaServerItem, "getMediaInfo",param, null);
     }
     }
 
 
-    public JSONObject getRtpInfo(IMediaServerItem mediaServerItem,String stream_id){
+    public JSONObject getRtpInfo(MediaServerItem mediaServerItem, String stream_id){
         Map<String, Object> param = new HashMap<>();
         Map<String, Object> param = new HashMap<>();
         param.put("stream_id",stream_id);
         param.put("stream_id",stream_id);
         return sendPost(mediaServerItem, "getRtpInfo",param, null);
         return sendPost(mediaServerItem, "getRtpInfo",param, null);
     }
     }
 
 
-    public JSONObject addFFmpegSource(IMediaServerItem mediaServerItem,String src_url, String dst_url, String timeout_ms,
+    public JSONObject addFFmpegSource(MediaServerItem mediaServerItem, String src_url, String dst_url, String timeout_ms,
                                       boolean enable_hls, boolean enable_mp4, String ffmpeg_cmd_key){
                                       boolean enable_hls, boolean enable_mp4, String ffmpeg_cmd_key){
         logger.info(src_url);
         logger.info(src_url);
         logger.info(dst_url);
         logger.info(dst_url);
@@ -185,41 +182,41 @@ public class ZLMRESTfulUtils {
         return sendPost(mediaServerItem, "addFFmpegSource",param, null);
         return sendPost(mediaServerItem, "addFFmpegSource",param, null);
     }
     }
 
 
-    public JSONObject delFFmpegSource(IMediaServerItem mediaServerItem,String key){
+    public JSONObject delFFmpegSource(MediaServerItem mediaServerItem, String key){
         Map<String, Object> param = new HashMap<>();
         Map<String, Object> param = new HashMap<>();
         param.put("key", key);
         param.put("key", key);
         return sendPost(mediaServerItem, "delFFmpegSource",param, null);
         return sendPost(mediaServerItem, "delFFmpegSource",param, null);
     }
     }
 
 
-    public JSONObject getMediaServerConfig(IMediaServerItem mediaServerItem){
+    public JSONObject getMediaServerConfig(MediaServerItem mediaServerItem){
         return sendPost(mediaServerItem, "getServerConfig",null, null);
         return sendPost(mediaServerItem, "getServerConfig",null, null);
     }
     }
 
 
-    public JSONObject setServerConfig(IMediaServerItem mediaServerItem, Map<String, Object> param){
+    public JSONObject setServerConfig(MediaServerItem mediaServerItem, Map<String, Object> param){
         return sendPost(mediaServerItem,"setServerConfig",param, null);
         return sendPost(mediaServerItem,"setServerConfig",param, null);
     }
     }
 
 
-    public JSONObject openRtpServer(IMediaServerItem mediaServerItem,Map<String, Object> param){
+    public JSONObject openRtpServer(MediaServerItem mediaServerItem, Map<String, Object> param){
         return sendPost(mediaServerItem, "openRtpServer",param, null);
         return sendPost(mediaServerItem, "openRtpServer",param, null);
     }
     }
 
 
-    public JSONObject closeRtpServer(IMediaServerItem mediaServerItem,Map<String, Object> param) {
+    public JSONObject closeRtpServer(MediaServerItem mediaServerItem, Map<String, Object> param) {
         return sendPost(mediaServerItem, "closeRtpServer",param, null);
         return sendPost(mediaServerItem, "closeRtpServer",param, null);
     }
     }
 
 
-    public JSONObject listRtpServer(IMediaServerItem mediaServerItem) {
+    public JSONObject listRtpServer(MediaServerItem mediaServerItem) {
         return sendPost(mediaServerItem, "listRtpServer",null, null);
         return sendPost(mediaServerItem, "listRtpServer",null, null);
     }
     }
 
 
-    public JSONObject startSendRtp(IMediaServerItem mediaServerItem,Map<String, Object> param) {
+    public JSONObject startSendRtp(MediaServerItem mediaServerItem, Map<String, Object> param) {
         return sendPost(mediaServerItem, "startSendRtp",param, null);
         return sendPost(mediaServerItem, "startSendRtp",param, null);
     }
     }
 
 
-    public JSONObject stopSendRtp(IMediaServerItem mediaServerItem,Map<String, Object> param) {
+    public JSONObject stopSendRtp(MediaServerItem mediaServerItem, Map<String, Object> param) {
         return sendPost(mediaServerItem, "stopSendRtp",param, null);
         return sendPost(mediaServerItem, "stopSendRtp",param, null);
     }
     }
 
 
-    public JSONObject addStreamProxy(IMediaServerItem mediaServerItem,String app, String stream, String url, boolean enable_hls, boolean enable_mp4, String rtp_type) {
+    public JSONObject addStreamProxy(MediaServerItem mediaServerItem, String app, String stream, String url, boolean enable_hls, boolean enable_mp4, String rtp_type) {
         Map<String, Object> param = new HashMap<>();
         Map<String, Object> param = new HashMap<>();
         param.put("vhost", "__defaultVhost__");
         param.put("vhost", "__defaultVhost__");
         param.put("app", app);
         param.put("app", app);
@@ -231,7 +228,7 @@ public class ZLMRESTfulUtils {
         return sendPost(mediaServerItem, "addStreamProxy",param, null);
         return sendPost(mediaServerItem, "addStreamProxy",param, null);
     }
     }
 
 
-    public JSONObject closeStreams(IMediaServerItem mediaServerItem,String app, String stream) {
+    public JSONObject closeStreams(MediaServerItem mediaServerItem, String app, String stream) {
         Map<String, Object> param = new HashMap<>();
         Map<String, Object> param = new HashMap<>();
         param.put("vhost", "__defaultVhost__");
         param.put("vhost", "__defaultVhost__");
         param.put("app", app);
         param.put("app", app);
@@ -240,17 +237,17 @@ public class ZLMRESTfulUtils {
         return sendPost(mediaServerItem, "close_streams",param, null);
         return sendPost(mediaServerItem, "close_streams",param, null);
     }
     }
 
 
-    public JSONObject getAllSession(IMediaServerItem mediaServerItem) {
+    public JSONObject getAllSession(MediaServerItem mediaServerItem) {
         return sendPost(mediaServerItem, "getAllSession",null, null);
         return sendPost(mediaServerItem, "getAllSession",null, null);
     }
     }
 
 
-    public void kickSessions(IMediaServerItem mediaServerItem, String localPortSStr) {
+    public void kickSessions(MediaServerItem mediaServerItem, String localPortSStr) {
         Map<String, Object> param = new HashMap<>();
         Map<String, Object> param = new HashMap<>();
         param.put("local_port", localPortSStr);
         param.put("local_port", localPortSStr);
         sendPost(mediaServerItem, "kick_sessions",param, null);
         sendPost(mediaServerItem, "kick_sessions",param, null);
     }
     }
 
 
-    public void getSnap(IMediaServerItem mediaServerItem, String flvUrl, int timeout_sec, int expire_sec, String targetPath, String fileName) {
+    public void getSnap(MediaServerItem mediaServerItem, String flvUrl, int timeout_sec, int expire_sec, String targetPath, String fileName) {
         Map<String, Object> param = new HashMap<>();
         Map<String, Object> param = new HashMap<>();
         param.put("url", flvUrl);
         param.put("url", flvUrl);
         param.put("timeout_sec", timeout_sec);
         param.put("timeout_sec", timeout_sec);

+ 39 - 41
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java

@@ -2,10 +2,7 @@ package com.genersoft.iot.vmp.media.zlm;
 
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.JSONObject;
-import com.genersoft.iot.vmp.conf.MediaConfig;
 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
-import com.genersoft.iot.vmp.gb28181.session.SsrcUtil;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import org.slf4j.Logger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.LoggerFactory;
@@ -20,29 +17,20 @@ public class ZLMRTPServerFactory {
 
 
     private Logger logger = LoggerFactory.getLogger("ZLMRTPServerFactory");
     private Logger logger = LoggerFactory.getLogger("ZLMRTPServerFactory");
 
 
-    @Autowired
-    private MediaConfig mediaConfig;
-
     @Autowired
     @Autowired
     private ZLMRESTfulUtils zlmresTfulUtils;
     private ZLMRESTfulUtils zlmresTfulUtils;
 
 
     private int[] portRangeArray = new int[2];
     private int[] portRangeArray = new int[2];
 
 
-    private int currentPort = 0;
-
-    private Map<String, Integer> currentStreams = null;
-
-    public int createRTPServer(IMediaServerItem mediaServerItem, String streamId) {
-        if (currentStreams == null) {
-            currentStreams = new HashMap<>();
-            JSONObject jsonObject = zlmresTfulUtils.listRtpServer(mediaServerItem);
-            if (jsonObject != null) {
-                JSONArray data = jsonObject.getJSONArray("data");
-                if (data != null) {
-                    for (int i = 0; i < data.size(); i++) {
-                        JSONObject dataItem = data.getJSONObject(i);
-                        currentStreams.put(dataItem.getString("stream_id"), dataItem.getInteger("port"));
-                    }
+    public int createRTPServer(MediaServerItem mediaServerItem, String streamId) {
+        Map<String, Integer> currentStreams = new HashMap<>();
+        JSONObject listRtpServerJsonResult = zlmresTfulUtils.listRtpServer(mediaServerItem);
+        if (listRtpServerJsonResult != null) {
+            JSONArray data = listRtpServerJsonResult.getJSONArray("data");
+            if (data != null) {
+                for (int i = 0; i < data.size(); i++) {
+                    JSONObject dataItem = data.getJSONObject(i);
+                    currentStreams.put(dataItem.getString("stream_id"), dataItem.getInteger("port"));
                 }
                 }
             }
             }
         }
         }
@@ -56,18 +44,18 @@ public class ZLMRTPServerFactory {
 
 
         Map<String, Object> param = new HashMap<>();
         Map<String, Object> param = new HashMap<>();
         int result = -1;
         int result = -1;
-        int newPort = getPortFromportRange();
+        int newPort = getPortFromportRange(mediaServerItem);
         param.put("port", newPort);
         param.put("port", newPort);
         param.put("enable_tcp", 1);
         param.put("enable_tcp", 1);
         param.put("stream_id", streamId);
         param.put("stream_id", streamId);
-        JSONObject jsonObject = zlmresTfulUtils.openRtpServer(mediaServerItem, param);
+        JSONObject openRtpServerResultJson = zlmresTfulUtils.openRtpServer(mediaServerItem, param);
 
 
-        if (jsonObject != null) {
-            switch (jsonObject.getInteger("code")){
+        if (openRtpServerResultJson != null) {
+            switch (openRtpServerResultJson.getInteger("code")){
                 case 0:
                 case 0:
                     result= newPort;
                     result= newPort;
                     break;
                     break;
-                case -300: // id已经存在, 可能已经在其他端口推流
+                case -300: // id已经存在, 可能已经在其他端口推流, TODO 也可能是设备不等ack就直接推流了, 需要查询与设置的推流ip端口是否一致
                     Map<String, Object> closeRtpServerParam = new HashMap<>();
                     Map<String, Object> closeRtpServerParam = new HashMap<>();
                     closeRtpServerParam.put("stream_id", streamId);
                     closeRtpServerParam.put("stream_id", streamId);
                     zlmresTfulUtils.closeRtpServer(mediaServerItem, closeRtpServerParam);
                     zlmresTfulUtils.closeRtpServer(mediaServerItem, closeRtpServerParam);
@@ -77,7 +65,7 @@ public class ZLMRTPServerFactory {
                     result= createRTPServer(mediaServerItem, streamId);
                     result= createRTPServer(mediaServerItem, streamId);
                     break;
                     break;
                 default:
                 default:
-                    logger.error("创建RTP Server 失败 {}: " + jsonObject.getString("msg"), newPort);
+                    logger.error("创建RTP Server 失败 {}: " + openRtpServerResultJson.getString("msg"), newPort);
                     break;
                     break;
             }
             }
         }else {
         }else {
@@ -87,7 +75,7 @@ public class ZLMRTPServerFactory {
         return result;
         return result;
     }
     }
 
 
-    public boolean closeRTPServer(IMediaServerItem serverItem, String streamId) {
+    public boolean closeRTPServer(MediaServerItem serverItem, String streamId) {
         boolean result = false;
         boolean result = false;
         if (serverItem !=null){
         if (serverItem !=null){
             Map<String, Object> param = new HashMap<>();
             Map<String, Object> param = new HashMap<>();
@@ -107,21 +95,25 @@ public class ZLMRTPServerFactory {
         return result;
         return result;
     }
     }
 
 
-    private int getPortFromportRange() {
+    private int getPortFromportRange(MediaServerItem mediaServerItem) {
+        int currentPort = mediaServerItem.getCurrentPort();
         if (currentPort == 0) {
         if (currentPort == 0) {
-            String[] portRangeStrArray = mediaConfig.getRtpPortRange().split(",");
+            String[] portRangeStrArray = mediaServerItem.getRtpPortRange().split(",");
             portRangeArray[0] = Integer.parseInt(portRangeStrArray[0]);
             portRangeArray[0] = Integer.parseInt(portRangeStrArray[0]);
             portRangeArray[1] = Integer.parseInt(portRangeStrArray[1]);
             portRangeArray[1] = Integer.parseInt(portRangeStrArray[1]);
         }
         }
 
 
         if (currentPort == 0 || currentPort++ > portRangeArray[1]) {
         if (currentPort == 0 || currentPort++ > portRangeArray[1]) {
             currentPort = portRangeArray[0];
             currentPort = portRangeArray[0];
+            mediaServerItem.setCurrentPort(currentPort);
             return portRangeArray[0];
             return portRangeArray[0];
         } else {
         } else {
             if (currentPort % 2 == 1) {
             if (currentPort % 2 == 1) {
                 currentPort++;
                 currentPort++;
             }
             }
-            return currentPort++;
+            currentPort++;
+            mediaServerItem.setCurrentPort(currentPort);
+            return currentPort;
         }
         }
     }
     }
 
 
@@ -135,10 +127,14 @@ public class ZLMRTPServerFactory {
      * @param tcp 是否为tcp
      * @param tcp 是否为tcp
      * @return SendRtpItem
      * @return SendRtpItem
      */
      */
-    public SendRtpItem createSendRtpItem(IMediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String deviceId, String channelId, boolean tcp){
-        String playSsrc = SsrcUtil.getPlaySsrc();
-        int localPort = createRTPServer(serverItem, SsrcUtil.getPlaySsrc());
+    public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String deviceId, String channelId, boolean tcp){
+
+        // 使用RTPServer 功能找一个可用的端口
+        String playSsrc = serverItem.getSsrcConfig().getPlaySsrc();
+        int localPort = createRTPServer(serverItem, playSsrc);
         if (localPort != -1) {
         if (localPort != -1) {
+            // TODO 高并发时可能因为未放入缓存而ssrc冲突
+            serverItem.getSsrcConfig().releaseSsrc(playSsrc);
             closeRTPServer(serverItem, playSsrc);
             closeRTPServer(serverItem, playSsrc);
         }else {
         }else {
             logger.error("没有可用的端口");
             logger.error("没有可用的端口");
@@ -168,10 +164,12 @@ public class ZLMRTPServerFactory {
      * @param tcp 是否为tcp
      * @param tcp 是否为tcp
      * @return SendRtpItem
      * @return SendRtpItem
      */
      */
-    public SendRtpItem createSendRtpItem(IMediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String app, String stream, String channelId, boolean tcp){
-        String playSsrc = SsrcUtil.getPlaySsrc();
-        int localPort = createRTPServer(serverItem, SsrcUtil.getPlaySsrc());
+    public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String app, String stream, String channelId, boolean tcp){
+        String playSsrc = serverItem.getSsrcConfig().getPlaySsrc();
+        int localPort = createRTPServer(serverItem, playSsrc);
         if (localPort != -1) {
         if (localPort != -1) {
+            // TODO 高并发时可能因为未放入缓存而ssrc冲突
+            serverItem.getSsrcConfig().releaseSsrc(ssrc);
             closeRTPServer(serverItem, playSsrc);
             closeRTPServer(serverItem, playSsrc);
         }else {
         }else {
             logger.error("没有可用的端口");
             logger.error("没有可用的端口");
@@ -194,7 +192,7 @@ public class ZLMRTPServerFactory {
     /**
     /**
      * 调用zlm RESTful API —— startSendRtp
      * 调用zlm RESTful API —— startSendRtp
      */
      */
-    public Boolean startSendRtpStream(IMediaServerItem mediaServerItem, Map<String, Object>param) {
+    public Boolean startSendRtpStream(MediaServerItem mediaServerItem, Map<String, Object>param) {
         Boolean result = false;
         Boolean result = false;
         JSONObject jsonObject = zlmresTfulUtils.startSendRtp(mediaServerItem, param);
         JSONObject jsonObject = zlmresTfulUtils.startSendRtp(mediaServerItem, param);
         if (jsonObject == null) {
         if (jsonObject == null) {
@@ -219,7 +217,7 @@ public class ZLMRTPServerFactory {
     /**
     /**
      * 查询待转推的流是否就绪
      * 查询待转推的流是否就绪
      */
      */
-    public Boolean isStreamReady(IMediaServerItem mediaServerItem, String app, String streamId) {
+    public Boolean isStreamReady(MediaServerItem mediaServerItem, String app, String streamId) {
         JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtmp", streamId);
         JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtmp", streamId);
         return (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online"));
         return (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online"));
     }
     }
@@ -229,7 +227,7 @@ public class ZLMRTPServerFactory {
      * @param streamId
      * @param streamId
      * @return
      * @return
      */
      */
-    public int totalReaderCount(IMediaServerItem mediaServerItem, String app, String streamId) {
+    public int totalReaderCount(MediaServerItem mediaServerItem, String app, String streamId) {
         JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtmp", streamId);
         JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtmp", streamId);
         return mediaInfo.getInteger("totalReaderCount");
         return mediaInfo.getInteger("totalReaderCount");
     }
     }
@@ -237,7 +235,7 @@ public class ZLMRTPServerFactory {
     /**
     /**
      * 调用zlm RESTful API —— stopSendRtp
      * 调用zlm RESTful API —— stopSendRtp
      */
      */
-    public Boolean stopSendRtpStream(IMediaServerItem mediaServerItem,Map<String, Object>param) {
+    public Boolean stopSendRtpStream(MediaServerItem mediaServerItem, Map<String, Object>param) {
         Boolean result = false;
         Boolean result = false;
         JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(mediaServerItem, param);
         JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(mediaServerItem, param);
         if (jsonObject == null) {
         if (jsonObject == null) {

+ 20 - 14
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java

@@ -4,22 +4,16 @@ import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.JSONObject;
 import com.genersoft.iot.vmp.conf.MediaConfig;
 import com.genersoft.iot.vmp.conf.MediaConfig;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
-import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.service.IMediaServerService;
-import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
 import com.genersoft.iot.vmp.service.IStreamProxyService;
 import com.genersoft.iot.vmp.service.IStreamProxyService;
 import org.slf4j.Logger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
 import org.springframework.boot.CommandLineRunner;
 import org.springframework.boot.CommandLineRunner;
 import org.springframework.core.annotation.Order;
 import org.springframework.core.annotation.Order;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
-import org.springframework.util.StringUtils;
 
 
-import javax.print.attribute.standard.Media;
 import java.util.*;
 import java.util.*;
 
 
 @Component
 @Component
@@ -47,16 +41,26 @@ public class ZLMRunner implements CommandLineRunner {
 
 
     @Override
     @Override
     public void run(String... strings) throws Exception {
     public void run(String... strings) throws Exception {
-        IMediaServerItem presetMediaServer = mediaServerService.getOneByHostAndPort(
+        // 清楚redis缓存的在线zlm信息
+        mediaServerService.clearMediaServerForOnline();
+
+        // 将配置文件的meida配置写入数据库
+        MediaServerItem presetMediaServer = mediaServerService.getOneByHostAndPort(
                 mediaConfig.getIp(), mediaConfig.getHttpPort());
                 mediaConfig.getIp(), mediaConfig.getHttpPort());
         if (presetMediaServer  != null) {
         if (presetMediaServer  != null) {
-            mediaConfig.setId(presetMediaServer.getId());
-            mediaServerService.update(mediaConfig);
+            MediaServerItem mediaSerItem = mediaConfig.getMediaSerItem();
+            mediaSerItem.setId(presetMediaServer.getId());
+            mediaServerService.update(mediaSerItem);
+        }else {
+            if (mediaConfig.getId() != null) {
+                MediaServerItem mediaSerItem = mediaConfig.getMediaSerItem();
+                mediaServerService.add(mediaSerItem);
+            }
         }
         }
 
 
         // 订阅 zlm启动事件, 新的zlm也会从这里进入系统
         // 订阅 zlm启动事件, 新的zlm也会从这里进入系统
         hookSubscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_server_started,null,
         hookSubscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_server_started,null,
-                (IMediaServerItem mediaServerItem, JSONObject response)->{
+                (MediaServerItem mediaServerItem, JSONObject response)->{
             ZLMServerConfig zlmServerConfig = JSONObject.toJavaObject(response, ZLMServerConfig.class);
             ZLMServerConfig zlmServerConfig = JSONObject.toJavaObject(response, ZLMServerConfig.class);
             if (zlmServerConfig !=null ) {
             if (zlmServerConfig !=null ) {
                 startGetMedia.remove(zlmServerConfig.getGeneralMediaServerId());
                 startGetMedia.remove(zlmServerConfig.getGeneralMediaServerId());
@@ -69,23 +73,25 @@ public class ZLMRunner implements CommandLineRunner {
         logger.info("等待默认zlm接入...");
         logger.info("等待默认zlm接入...");
 
 
         // 获取所有的zlm, 并开启主动连接
         // 获取所有的zlm, 并开启主动连接
-        List<IMediaServerItem> all = mediaServerService.getAll();
+        List<MediaServerItem> all = mediaServerService.getAll();
         if (presetMediaServer == null) {
         if (presetMediaServer == null) {
             all.add(mediaConfig.getMediaSerItem());
             all.add(mediaConfig.getMediaSerItem());
         }
         }
-        for (IMediaServerItem mediaServerItem : all) {
+        for (MediaServerItem mediaServerItem : all) {
             if (startGetMedia == null) startGetMedia = new HashMap<>();
             if (startGetMedia == null) startGetMedia = new HashMap<>();
             startGetMedia.put(mediaServerItem.getId(), true);
             startGetMedia.put(mediaServerItem.getId(), true);
             new Thread(() -> {
             new Thread(() -> {
                 ZLMServerConfig zlmServerConfig = getMediaServerConfig(mediaServerItem);
                 ZLMServerConfig zlmServerConfig = getMediaServerConfig(mediaServerItem);
                 if (zlmServerConfig != null) {
                 if (zlmServerConfig != null) {
+                    zlmServerConfig.setIp(mediaServerItem.getIp());
+                    zlmServerConfig.setHttpPort(mediaServerItem.getHttpPort());
                     startGetMedia.remove(mediaServerItem.getId());
                     startGetMedia.remove(mediaServerItem.getId());
                     mediaServerService.handLeZLMServerConfig(zlmServerConfig);
                     mediaServerService.handLeZLMServerConfig(zlmServerConfig);
                 }
                 }
             }).start();
             }).start();
         }
         }
         Timer timer = new Timer();
         Timer timer = new Timer();
-        // 1分钟后未连接到则不再去主动连接
+        // 2分钟后未连接到则不再去主动连接, TODO 并对重启前使用此在zlm的通道发送bye
         timer.schedule(new TimerTask() {
         timer.schedule(new TimerTask() {
             @Override
             @Override
             public void run() {
             public void run() {
@@ -100,7 +106,7 @@ public class ZLMRunner implements CommandLineRunner {
         }, 60 * 1000 * 2);
         }, 60 * 1000 * 2);
     }
     }
 
 
-    public ZLMServerConfig getMediaServerConfig(IMediaServerItem mediaServerItem) {
+    public ZLMServerConfig getMediaServerConfig(MediaServerItem mediaServerItem) {
         if ( startGetMedia.get(mediaServerItem.getId()) == null || !startGetMedia.get(mediaServerItem.getId())) return null;
         if ( startGetMedia.get(mediaServerItem.getId()) == null || !startGetMedia.get(mediaServerItem.getId())) return null;
         JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem);
         JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem);
         ZLMServerConfig ZLMServerConfig = null;
         ZLMServerConfig ZLMServerConfig = null;

+ 0 - 92
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/IMediaServerItem.java

@@ -1,92 +0,0 @@
-package com.genersoft.iot.vmp.media.zlm.dto;
-
-public interface IMediaServerItem {
-
-    String getId();
-
-    void setId(String id);
-
-    String getIp();
-
-    void setIp(String ip);
-
-    String getHookIp();
-
-    void setHookIp(String hookIp);
-
-    String getSdpIp();
-
-    void setSdpIp(String sdpIp);
-
-    String getStreamIp();
-
-    void setStreamIp(String streamIp);
-
-    int getHttpPort();
-
-    void setHttpPort(int httpPort);
-
-    int getHttpSSlPort();
-
-    void setHttpSSlPort(int httpSSlPort);
-
-    int getRtmpPort();
-
-    void setRtmpPort(int rtmpPort);
-
-    int getRtmpSSlPort();
-
-    void setRtmpSSlPort(int rtmpSSlPort);
-
-    int getRtpProxyPort();
-
-    void setRtpProxyPort(int rtpProxyPort);
-
-    int getRtspPort();
-
-    void setRtspPort(int rtspPort);
-
-    int getRtspSSLPort();
-
-    void setRtspSSLPort(int rtspSSLPort);
-
-    boolean isAutoConfig();
-
-    void setAutoConfig(boolean autoConfig);
-
-    String getSecret();
-
-    void setSecret(String secret);
-
-    String getStreamNoneReaderDelayMS();
-
-    void setStreamNoneReaderDelayMS(String streamNoneReaderDelayMS);
-
-    boolean isRtpEnable();
-
-    void setRtpEnable(boolean rtpEnable);
-
-    String getRtpPortRange();
-
-    void setRtpPortRange(String rtpPortRange);
-
-    int getRecordAssistPort();
-
-    void setRecordAssistPort(int recordAssistPort);
-
-    boolean isDocker();
-
-    void setDocker(boolean docker);
-
-    String getUpdateTime();
-
-    void setUpdateTime(String updateTime);
-
-    String getCreateTime();
-
-    void setCreateTime(String createTime);
-
-    int getCount();
-
-    void setCount(int count);
-}

+ 41 - 13
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java

@@ -1,10 +1,13 @@
 package com.genersoft.iot.vmp.media.zlm.dto;
 package com.genersoft.iot.vmp.media.zlm.dto;
 
 
 
 
+import com.genersoft.iot.vmp.gb28181.session.SsrcConfig;
 import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
 import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
 import org.springframework.util.StringUtils;
 import org.springframework.util.StringUtils;
 
 
-public class MediaServerItem implements IMediaServerItem{
+import java.util.HashMap;
+
+public class MediaServerItem{
 
 
     private String id;
     private String id;
 
 
@@ -46,9 +49,18 @@ public class MediaServerItem implements IMediaServerItem{
 
 
     private String updateTime;
     private String updateTime;
 
 
-    private boolean docker;
+    private boolean defaultServer;
+
+    private SsrcConfig ssrcConfig;
+
+    private int currentPort;
+
 
 
-    private int count;
+    /**
+     * 每一台ZLM都有一套独立的SSRC列表
+     * 在ApplicationCheckRunner里对mediaServerSsrcMap进行初始化
+     */
+    private HashMap<String, SsrcConfig> mediaServerSsrcMap;
 
 
     public MediaServerItem() {
     public MediaServerItem() {
     }
     }
@@ -218,14 +230,12 @@ public class MediaServerItem implements IMediaServerItem{
         this.recordAssistPort = recordAssistPort;
         this.recordAssistPort = recordAssistPort;
     }
     }
 
 
-    @Override
-    public boolean isDocker() {
-        return docker;
+    public boolean isDefaultServer() {
+        return defaultServer;
     }
     }
 
 
-    @Override
-    public void setDocker(boolean docker) {
-        this.docker = docker;
+    public void setDefaultServer(boolean defaultServer) {
+        this.defaultServer = defaultServer;
     }
     }
 
 
     public String getCreateTime() {
     public String getCreateTime() {
@@ -244,11 +254,29 @@ public class MediaServerItem implements IMediaServerItem{
         this.updateTime = updateTime;
         this.updateTime = updateTime;
     }
     }
 
 
-    public int getCount() {
-        return count;
+    public HashMap<String, SsrcConfig> getMediaServerSsrcMap() {
+        return mediaServerSsrcMap;
+    }
+
+    public void setMediaServerSsrcMap(HashMap<String, SsrcConfig> mediaServerSsrcMap) {
+        this.mediaServerSsrcMap = mediaServerSsrcMap;
+    }
+
+    public SsrcConfig getSsrcConfig() {
+        return ssrcConfig;
+    }
+
+    public void setSsrcConfig(SsrcConfig ssrcConfig) {
+        this.ssrcConfig = ssrcConfig;
     }
     }
 
 
-    public void setCount(int count) {
-        this.count = count;
+    public int getCurrentPort() {
+        return currentPort;
     }
     }
+
+    public void setCurrentPort(int currentPort) {
+        this.currentPort = currentPort;
+    }
+
+
 }
 }

+ 20 - 10
src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java

@@ -3,8 +3,8 @@ package com.genersoft.iot.vmp.service;
 import com.genersoft.iot.vmp.conf.MediaConfig;
 import com.genersoft.iot.vmp.conf.MediaConfig;
 import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
 import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
+import com.genersoft.iot.vmp.service.bean.SSRCInfo;
 
 
 import java.util.List;
 import java.util.List;
 
 
@@ -13,11 +13,13 @@ import java.util.List;
  */
  */
 public interface IMediaServerService {
 public interface IMediaServerService {
 
 
-    List<IMediaServerItem> getAll();
+    List<MediaServerItem> getAll();
 
 
-    IMediaServerItem getOne(String generalMediaServerId);
+    List<MediaServerItem> getAllOnline();
 
 
-    IMediaServerItem getOneByHostAndPort(String host, int port);
+    MediaServerItem getOne(String generalMediaServerId);
+
+    MediaServerItem getOneByHostAndPort(String host, int port);
 
 
     /**
     /**
      * 新的节点加入
      * 新的节点加入
@@ -26,19 +28,27 @@ public interface IMediaServerService {
      */
      */
     void handLeZLMServerConfig(ZLMServerConfig zlmServerConfig);
     void handLeZLMServerConfig(ZLMServerConfig zlmServerConfig);
 
 
-    void updateServerCatch(IMediaServerItem mediaServerItem, Integer count, Boolean b);
-
-    IMediaServerItem getMediaServerForMinimumLoad();
+    MediaServerItem getMediaServerForMinimumLoad();
 
 
-    void setZLMConfig(IMediaServerItem mediaServerItem);
+    void setZLMConfig(MediaServerItem mediaServerItem);
 
 
-    void init();
+    SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId);
 
 
     void closeRTPServer(Device device, String channelId);
     void closeRTPServer(Device device, String channelId);
 
 
-    void update(MediaConfig mediaConfig);
+    void clearRTPServer(MediaServerItem mediaServerItem);
+
+    void update(MediaServerItem mediaSerItem);
 
 
     void addCount(String mediaServerId);
     void addCount(String mediaServerId);
 
 
     void removeCount(String mediaServerId);
     void removeCount(String mediaServerId);
+
+    void releaseSsrc(MediaServerItem mediaServerItem, String ssrc);
+
+    void clearMediaServerForOnline();
+
+    void add(MediaServerItem mediaSerItem);
+
+    void resetOnlineServerItem(MediaServerItem serverItem);
 }
 }

+ 2 - 3
src/main/java/com/genersoft/iot/vmp/service/IMediaService.java

@@ -2,7 +2,6 @@ package com.genersoft.iot.vmp.service;
 
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONArray;
 import com.genersoft.iot.vmp.common.StreamInfo;
 import com.genersoft.iot.vmp.common.StreamInfo;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 
 
 /**
 /**
@@ -33,7 +32,7 @@ public interface IMediaService {
      * @param stream
      * @param stream
      * @return
      * @return
      */
      */
-    StreamInfo getStreamInfoByAppAndStream(IMediaServerItem mediaServerItem, String app, String stream, JSONArray tracks);
+    StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaServerItem, String app, String stream, JSONArray tracks);
 
 
     /**
     /**
      * 根据应用名和流ID获取播放地址, 只是地址拼接,返回的ip使用远程访问ip,适用与zlm与wvp在一台主机的情况
      * 根据应用名和流ID获取播放地址, 只是地址拼接,返回的ip使用远程访问ip,适用与zlm与wvp在一台主机的情况
@@ -41,5 +40,5 @@ public interface IMediaService {
      * @param stream
      * @param stream
      * @return
      * @return
      */
      */
-    StreamInfo getStreamInfoByAppAndStream(IMediaServerItem mediaInfo, String app, String stream, JSONArray tracks, String addr);
+    StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, JSONArray tracks, String addr);
 }
 }

+ 4 - 5
src/main/java/com/genersoft/iot/vmp/service/IPlayService.java

@@ -4,7 +4,6 @@ import com.alibaba.fastjson.JSONObject;
 import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
 import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
 
 
@@ -13,10 +12,10 @@ import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
  */
  */
 public interface IPlayService {
 public interface IPlayService {
 
 
-    void onPublishHandlerForPlayBack(IMediaServerItem mediaServerItem,JSONObject resonse, String deviceId, String channelId, String uuid);
-    void onPublishHandlerForPlay(IMediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid);
+    void onPublishHandlerForPlayBack(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid);
+    void onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid);
 
 
-    PlayResult play(IMediaServerItem mediaServerItem, String deviceId, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
+    PlayResult play(MediaServerItem mediaServerItem, String deviceId, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
 
 
-    IMediaServerItem getNewMediaServerItem(Device device);
+    MediaServerItem getNewMediaServerItem(Device device);
 }
 }

+ 1 - 2
src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java

@@ -1,7 +1,6 @@
 package com.genersoft.iot.vmp.service;
 package com.genersoft.iot.vmp.service;
 
 
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.JSONObject;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
 import com.github.pagehelper.PageInfo;
 import com.github.pagehelper.PageInfo;
@@ -63,5 +62,5 @@ public interface IStreamProxyService {
      * 获取ffmpeg.cmd模板
      * 获取ffmpeg.cmd模板
      * @return
      * @return
      */
      */
-    JSONObject getFFmpegCMDs(IMediaServerItem mediaServerItem);
+    JSONObject getFFmpegCMDs(MediaServerItem mediaServerItem);
 }
 }

+ 2 - 2
src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java

@@ -1,7 +1,7 @@
 package com.genersoft.iot.vmp.service;
 package com.genersoft.iot.vmp.service;
 
 
 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
+import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
 import com.github.pagehelper.PageInfo;
 import com.github.pagehelper.PageInfo;
 
 
@@ -9,7 +9,7 @@ import java.util.List;
 
 
 public interface IStreamPushService {
 public interface IStreamPushService {
 
 
-    List<StreamPushItem> handleJSON(String json, IMediaServerItem mediaServerItem);
+    List<StreamPushItem> handleJSON(String json, MediaServerItem mediaServerItem);
 
 
     /**
     /**
      * 将应用名和流ID加入国标关联
      * 将应用名和流ID加入国标关联

+ 38 - 0
src/main/java/com/genersoft/iot/vmp/service/bean/SSRCInfo.java

@@ -0,0 +1,38 @@
+package com.genersoft.iot.vmp.service.bean;
+
+public class SSRCInfo {
+
+    private int port;
+    private String ssrc;
+    private String StreamId;
+
+    public SSRCInfo(int port, String ssrc, String streamId) {
+        this.port = port;
+        this.ssrc = ssrc;
+        StreamId = streamId;
+    }
+
+    public int getPort() {
+        return port;
+    }
+
+    public void setPort(int port) {
+        this.port = port;
+    }
+
+    public String getSsrc() {
+        return ssrc;
+    }
+
+    public void setSsrc(String ssrc) {
+        this.ssrc = ssrc;
+    }
+
+    public String getStreamId() {
+        return StreamId;
+    }
+
+    public void setStreamId(String streamId) {
+        StreamId = streamId;
+    }
+}

+ 221 - 164
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java

@@ -1,29 +1,32 @@
 package com.genersoft.iot.vmp.service.impl;
 package com.genersoft.iot.vmp.service.impl;
 
 
-import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.JSONObject;
-import com.genersoft.iot.vmp.common.StreamInfo;
+import com.genersoft.iot.vmp.common.VideoManagerConstants;
 import com.genersoft.iot.vmp.conf.MediaConfig;
 import com.genersoft.iot.vmp.conf.MediaConfig;
-import com.genersoft.iot.vmp.conf.ProxyServletConfig;
+import com.genersoft.iot.vmp.conf.SipConfig;
 import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.gb28181.bean.Device;
+import com.genersoft.iot.vmp.gb28181.session.SsrcConfig;
 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
 import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
 import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
-import com.genersoft.iot.vmp.media.zlm.dto.ZLMRunInfo;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.service.IMediaServerService;
+import com.genersoft.iot.vmp.service.bean.SSRCInfo;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.dao.MediaServerMapper;
 import com.genersoft.iot.vmp.storager.dao.MediaServerMapper;
-import org.mitre.dsmiley.httpproxy.ProxyServlet;
+import com.genersoft.iot.vmp.utils.redis.JedisUtil;
+import com.genersoft.iot.vmp.utils.redis.RedisUtil;
 import org.slf4j.Logger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.core.annotation.Order;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 
 
+import java.sql.Array;
 import java.text.SimpleDateFormat;
 import java.text.SimpleDateFormat;
 import java.util.*;
 import java.util.*;
 
 
@@ -31,15 +34,13 @@ import java.util.*;
  * 媒体服务器节点管理
  * 媒体服务器节点管理
  */
  */
 @Service
 @Service
-public class MediaServerServiceImpl implements IMediaServerService {
+@Order(value=2)
+public class MediaServerServiceImpl implements IMediaServerService, CommandLineRunner {
 
 
     private final static Logger logger = LoggerFactory.getLogger(MediaServerServiceImpl.class);
     private final static Logger logger = LoggerFactory.getLogger(MediaServerServiceImpl.class);
 
 
-    private Map<String, IMediaServerItem> zlmServers = new HashMap<>(); // 所有数据库的zlm的缓存
-    private Map<String, Integer> zlmServerStatus = new LinkedHashMap<>(); // 所有上线的zlm的缓存以及负载
-
-    @Value("${sip.ip}")
-    private String sipIp;
+    @Autowired
+    private SipConfig sipConfig;
 
 
     @Value("${server.ssl.enabled:false}")
     @Value("${server.ssl.enabled:false}")
     private boolean sslEnabled;
     private boolean sslEnabled;
@@ -56,7 +57,6 @@ public class MediaServerServiceImpl implements IMediaServerService {
     @Autowired
     @Autowired
     private MediaServerMapper mediaServerMapper;
     private MediaServerMapper mediaServerMapper;
 
 
-
     @Autowired
     @Autowired
     private IRedisCatchStorage redisCatchStorage;
     private IRedisCatchStorage redisCatchStorage;
 
 
@@ -66,53 +66,134 @@ public class MediaServerServiceImpl implements IMediaServerService {
     @Autowired
     @Autowired
     private ZLMRTPServerFactory zlmrtpServerFactory;
     private ZLMRTPServerFactory zlmrtpServerFactory;
 
 
-    private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+    @Autowired
+    private RedisUtil redisUtil;
+
+    @Autowired
+    JedisUtil jedisUtil;
+
+    private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 
 
     /**
     /**
      * 初始化
      * 初始化
      */
      */
     @Override
     @Override
-    public void init() {
-        zlmServers.clear();
-        zlmServerStatus.clear();
+    public void run(String... args) throws Exception {
+        logger.info("Media Server 缓存初始化");
         List<MediaServerItem> mediaServerItemList = mediaServerMapper.queryAll();
         List<MediaServerItem> mediaServerItemList = mediaServerMapper.queryAll();
-        for (IMediaServerItem mediaServerItem : mediaServerItemList) {
-            zlmServers.put(mediaServerItem.getId(), mediaServerItem);
+        for (MediaServerItem mediaServerItem : mediaServerItemList) {
+            // 更新
+            if (mediaServerItem.getSsrcConfig() == null) {
+                SsrcConfig ssrcConfig = new SsrcConfig(mediaServerItem.getId(), null, sipConfig.getSipDomain());
+                mediaServerItem.setSsrcConfig(ssrcConfig);
+                redisUtil.set(VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerItem.getId(), mediaServerItem);
+            }
+            // 查询redis是否存在此mediaServer
+            String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerItem.getId();
+            if (!redisUtil.hasKey(key)) {
+                redisUtil.set(key, mediaServerItem);
+            }
+        }
+    }
+
+    @Override
+    public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId) {
+        if (mediaServerItem == null || mediaServerItem.getId() == null) return null;
+        // 获取mediaServer可用的ssrc
+        String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerItem.getId();
+
+        SsrcConfig ssrcConfig = mediaServerItem.getSsrcConfig();
+        if (ssrcConfig == null) {
+            logger.info("media server [ {} ] ssrcConfig is null", mediaServerItem.getId());
+            return null;
+        }else {
+            String ssrc = ssrcConfig.getPlaySsrc();
+            if (streamId == null) streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
+            int rtpServerPort = mediaServerItem.getRtpProxyPort();
+            if (mediaServerItem.isRtpEnable()) {
+                rtpServerPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId);
+            }
+            redisUtil.set(key, mediaServerItem);
+            return new SSRCInfo(rtpServerPort, ssrc, streamId);
         }
         }
     }
     }
 
 
     @Override
     @Override
     public void closeRTPServer(Device device, String channelId) {
     public void closeRTPServer(Device device, String channelId) {
-        StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId);
-        IMediaServerItem mediaServerItem = null;
-        if (streamInfo != null) {
-            mediaServerItem = this.getOne (streamInfo.getMediaServerId());
+        String mediaServerId = streamSession.getMediaServerId(device.getDeviceId(), channelId);
+        MediaServerItem mediaServerItem = this.getOne(mediaServerId);
+        if (mediaServerItem != null) {
+            String streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
+            zlmrtpServerFactory.closeRTPServer(mediaServerItem, streamId);
+            releaseSsrc(mediaServerItem, streamSession.getSSRC(device.getDeviceId(), channelId));
         }
         }
-        String streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
-        zlmrtpServerFactory.closeRTPServer(mediaServerItem, streamId);
         streamSession.remove(device.getDeviceId(), channelId);
         streamSession.remove(device.getDeviceId(), channelId);
     }
     }
 
 
     @Override
     @Override
-    public void update(MediaConfig mediaConfig) {
+    public void releaseSsrc(MediaServerItem mediaServerItem, String ssrc) {
+        if (mediaServerItem == null || ssrc == null) return;
+        SsrcConfig ssrcConfig = mediaServerItem.getSsrcConfig();
+        ssrcConfig.releaseSsrc(ssrc);
+        mediaServerItem.setSsrcConfig(ssrcConfig);
+        String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerItem.getId();
+        redisUtil.set(key, mediaServerItem);
+    }
 
 
+    /**
+     * zlm 重启后重置他的推流信息, TODO 给正在使用的设备发送停止命令
+     * @param mediaServerItem
+     */
+    @Override
+    public void clearRTPServer(MediaServerItem mediaServerItem) {
+        mediaServerItem.setSsrcConfig(new SsrcConfig(mediaServerItem.getId(), null, sipConfig.getSipDomain()));
+        redisUtil.zAdd(VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX, mediaServerItem.getId(), 0);
     }
     }
 
 
+
     @Override
     @Override
-    public List<IMediaServerItem> getAll() {
-        if (zlmServers.size() == 0) {
-            init();
+    public void update(MediaServerItem mediaSerItem) {
+        mediaServerMapper.update(mediaSerItem);
+        MediaServerItem mediaServerItemInRedis = getOne(mediaSerItem.getId());
+        MediaServerItem mediaServerItemInDataBase = mediaServerMapper.queryOne(mediaSerItem.getId());
+        if (mediaServerItemInRedis != null && mediaServerItemInRedis.getSsrcConfig() != null) {
+            mediaServerItemInDataBase.setSsrcConfig(mediaServerItemInRedis.getSsrcConfig());
+        }else {
+            mediaServerItemInDataBase.setSsrcConfig(
+                    new SsrcConfig(
+                            mediaServerItemInDataBase.getId(),
+                            null,
+                            sipConfig.getSipDomain()
+                    )
+            );
         }
         }
-        List<IMediaServerItem> result = new ArrayList<>();
-        for (String id : zlmServers.keySet()) {
-            IMediaServerItem mediaServerItem = zlmServers.get(id);
-            mediaServerItem.setCount(zlmServerStatus.get(id) == null ? 0 : zlmServerStatus.get(id));
-            result.add(mediaServerItem);
+        String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerItemInDataBase.getId();
+        redisUtil.set(key, mediaServerItemInDataBase);
+    }
+
+    @Override
+    public List<MediaServerItem> getAll() {
+        List<MediaServerItem> result = new ArrayList<>();
+        List<Object> mediaServerKeys = redisUtil.scan(String.format("%S*", VideoManagerConstants.MEDIA_SERVER_PREFIX));
+        for (int i = 0; i < mediaServerKeys.size(); i++) {
+            String key = (String) mediaServerKeys.get(i);
+            result.add((MediaServerItem)redisUtil.get(key));
         }
         }
         return result;
         return result;
+    }
 
 
-
-//        return mediaServerMapper.queryAll();
+    @Override
+    public List<MediaServerItem> getAllOnline() {
+        String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX;
+        Set<String> mediaServerIdSet = redisUtil.zRevRange(key, 0, -1);
+        List<MediaServerItem> result = new ArrayList<>();
+        if (mediaServerIdSet != null && mediaServerIdSet.size() > 0) {
+            for (String mediaServerId : mediaServerIdSet) {
+                String serverKey = VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerId;
+                result.add((MediaServerItem) redisUtil.get(serverKey));
+            }
+        }
+        return result;
     }
     }
 
 
     /**
     /**
@@ -121,26 +202,28 @@ public class MediaServerServiceImpl implements IMediaServerService {
      * @return MediaServerItem
      * @return MediaServerItem
      */
      */
     @Override
     @Override
-    public IMediaServerItem getOne(String mediaServerId) {
-        if (mediaServerId ==null) return null;
-        IMediaServerItem mediaServerItem = zlmServers.get(mediaServerId);
-        if (mediaServerItem != null) {
-            mediaServerItem.setCount(zlmServerStatus.get(mediaServerId) == null ? 0 : zlmServerStatus.get(mediaServerId));
-            return mediaServerItem;
-        }else {
-            IMediaServerItem item = mediaServerMapper.queryOne(mediaServerId);
-            if (item != null) {
-                zlmServers.put(item.getId(), item);
-            }
-            return item;
-        }
+    public MediaServerItem getOne(String mediaServerId) {
+        if (mediaServerId == null) return null;
+        String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerId;
+        return (MediaServerItem)redisUtil.get(key);
     }
     }
 
 
     @Override
     @Override
-    public IMediaServerItem getOneByHostAndPort(String host, int port) {
+    public MediaServerItem getOneByHostAndPort(String host, int port) {
         return mediaServerMapper.queryOneByHostAndPort(host, port);
         return mediaServerMapper.queryOneByHostAndPort(host, port);
     }
     }
 
 
+    @Override
+    public void clearMediaServerForOnline() {
+        String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX;
+        redisUtil.del(key);
+    }
+
+    @Override
+    public void add(MediaServerItem mediaSerItem) {
+        mediaServerMapper.add(mediaSerItem);
+    }
+
     /**
     /**
      * 处理zlm上线
      * 处理zlm上线
      * @param zlmServerConfig zlm上线携带的参数
      * @param zlmServerConfig zlm上线携带的参数
@@ -150,111 +233,100 @@ public class MediaServerServiceImpl implements IMediaServerService {
         logger.info("[ {} ]-[ {}:{} ]已连接",
         logger.info("[ {} ]-[ {}:{} ]已连接",
                 zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort());
                 zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort());
 
 
-        IMediaServerItem serverItem = getOne(zlmServerConfig.getGeneralMediaServerId());
-        String now = this.format.format(new Date(System.currentTimeMillis()));
-        if (serverItem != null) {
-            serverItem.setSecret(zlmServerConfig.getApiSecret());
-            serverItem.setIp(zlmServerConfig.getIp());
+        MediaServerItem serverItem = mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId());
+        if (serverItem == null) {
+            serverItem = mediaServerMapper.queryOneByHostAndPort(zlmServerConfig.getIp(), zlmServerConfig.getHttpPort());
+        }
+        if (zlmServerConfig.getGeneralMediaServerId().equals(mediaConfig.getId())
+                || (zlmServerConfig.getIp().equals(mediaConfig.getIp()) && zlmServerConfig.getHttpPort() == mediaConfig.getHttpPort())) {
+            // 配置文件的zlm
             // 如果是配置文件中的zlm。 也就是默认zlm。 一切以配置文件内容为准
             // 如果是配置文件中的zlm。 也就是默认zlm。 一切以配置文件内容为准
-            // docker部署不会使用zlm配置的端口号;
-            // 直接编译部署的使用配置文件的端口号,如果zlm修改配改了配置,wvp自动修改
-
-            if (serverItem.getId().equals(mediaConfig.getId())
-                    || (serverItem.getIp().equals(mediaConfig.getIp()) && serverItem.getHttpPort() == mediaConfig.getHttpPort())) {
-                // 配置文件的zlm
-                mediaConfig.setId(zlmServerConfig.getGeneralMediaServerId());
-                mediaConfig.setUpdateTime(now);
-                if (mediaConfig.getHttpPort() == 0) mediaConfig.setHttpPort(zlmServerConfig.getHttpPort());
-                if (mediaConfig.getHttpSSlPort() == 0) mediaConfig.setHttpSSlPort(zlmServerConfig.getHttpSSLport());
-                if (mediaConfig.getRtmpPort() == 0) mediaConfig.setRtmpPort(zlmServerConfig.getRtmpPort());
-                if (mediaConfig.getRtmpSSlPort() == 0) mediaConfig.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort());
-                if (mediaConfig.getRtspPort() == 0) mediaConfig.setRtspPort(zlmServerConfig.getRtspPort());
-                if (mediaConfig.getRtspSSLPort() == 0) mediaConfig.setRtspSSLPort(zlmServerConfig.getRtspSSlport());
-                if (mediaConfig.getRtpProxyPort() == 0) mediaConfig.setRtpProxyPort(zlmServerConfig.getRtpProxyPort());
-                mediaServerMapper.update(mediaConfig);
-                serverItem = mediaConfig.getMediaSerItem();
-                setZLMConfig(mediaConfig);
-            }else {
-                if (!serverItem.isDocker()) {
-                    serverItem.setHttpPort(zlmServerConfig.getHttpPort());
-                    serverItem.setHttpSSlPort(zlmServerConfig.getHttpSSLport());
-                    serverItem.setRtmpPort(zlmServerConfig.getRtmpPort());
-                    serverItem.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort());
-                    serverItem.setRtpProxyPort(zlmServerConfig.getRtpProxyPort());
-                    serverItem.setRtspPort(zlmServerConfig.getRtspPort());
-
+            // docker部署不会使用zlm配置的端口号不是默认的则不做更新, 配置修改需要自行修改server配置;
+            MediaServerItem serverItemFromConfig = mediaConfig.getMediaSerItem();
+            serverItemFromConfig.setId(zlmServerConfig.getGeneralMediaServerId());
+            if (mediaConfig.getHttpPort() == 0) serverItemFromConfig.setHttpPort(zlmServerConfig.getHttpPort());
+            if (mediaConfig.getHttpSSlPort() == 0) serverItemFromConfig.setHttpSSlPort(zlmServerConfig.getHttpSSLport());
+            if (mediaConfig.getRtmpPort() == 0) serverItemFromConfig.setRtmpPort(zlmServerConfig.getRtmpPort());
+            if (mediaConfig.getRtmpSSlPort() == 0) serverItemFromConfig.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort());
+            if (mediaConfig.getRtspPort() == 0) serverItemFromConfig.setRtspPort(zlmServerConfig.getRtspPort());
+            if (mediaConfig.getRtspSSLPort() == 0) serverItemFromConfig.setRtspSSLPort(zlmServerConfig.getRtspSSlport());
+            if (mediaConfig.getRtpProxyPort() == 0) serverItemFromConfig.setRtpProxyPort(zlmServerConfig.getRtpProxyPort());
+            if (serverItem != null){
+                // 可能是同一个zlm但id发生了变化
+                if (!serverItem.getId().equals(zlmServerConfig.getGeneralMediaServerId())) {
+                    mediaServerMapper.delOne(serverItem.getId());
+                    redisUtil.del(VideoManagerConstants.MEDIA_SERVER_PREFIX + serverItem.getId());
+
+                    String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + serverItemFromConfig.getId();
+                    serverItemFromConfig.setSsrcConfig(new SsrcConfig(serverItemFromConfig.getId(), null, sipConfig.getSipDomain()));
+                    redisUtil.set(key, serverItemFromConfig);
+                    mediaServerMapper.add(serverItemFromConfig);
+                }else {
+                    mediaServerMapper.update(serverItemFromConfig);
                 }
                 }
-                serverItem.setUpdateTime(now);
-                mediaServerMapper.update(serverItem);
-                setZLMConfig(serverItem);
+            }else {
+                String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + serverItemFromConfig.getId();
+                serverItemFromConfig.setSsrcConfig(new SsrcConfig(serverItemFromConfig.getId(), null, sipConfig.getSipDomain()));
+                redisUtil.set(key, serverItemFromConfig);
+                mediaServerMapper.add(serverItemFromConfig);
             }
             }
+            resetOnlineServerItem(serverItemFromConfig);
+            setZLMConfig(serverItemFromConfig);
         }else {
         }else {
-            if (zlmServerConfig.getGeneralMediaServerId().equals(mediaConfig.getId())
-                    || (zlmServerConfig.getIp().equals(mediaConfig.getIp()) && zlmServerConfig.getHttpPort() == mediaConfig.getHttpPort())) {
-                mediaConfig.setId(zlmServerConfig.getGeneralMediaServerId());
-                mediaConfig.setCreateTime(now);
-                mediaConfig.setUpdateTime(now);
-                serverItem = mediaConfig.getMediaSerItem();
-                mediaServerMapper.add(mediaConfig);
-            }else {
-                // 一个新的zlm接入wvp
-                serverItem = new MediaServerItem(zlmServerConfig, sipIp);
-                serverItem.setCreateTime(now);
-                serverItem.setUpdateTime(now);
+            String now = this.format.format(new Date(System.currentTimeMillis()));
+            if (serverItem == null){
+                    // 一个新的zlm接入wvp
+                    serverItem = new MediaServerItem(zlmServerConfig, sipConfig.getSipIp());
+                    serverItem.setCreateTime(now);
+                    serverItem.setUpdateTime(now);
+                String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + serverItem.getId();
+                serverItem.setSsrcConfig(new SsrcConfig(serverItem.getId(), null, sipConfig.getSipDomain()));
+                redisUtil.set(key, serverItem);
+                // 存入数据库
                 mediaServerMapper.add(serverItem);
                 mediaServerMapper.add(serverItem);
+                setZLMConfig(serverItem);
             }
             }
+            resetOnlineServerItem(serverItem);
         }
         }
-        // 更新缓存
-        if (zlmServerStatus.get(serverItem.getId()) == null) {
-            zlmServers.put(serverItem.getId(), serverItem);
-            zlmServerStatus.put(serverItem.getId(),0);
-        }
-        // 查询服务流数量
-        IMediaServerItem finalServerItem = serverItem;
-        zlmresTfulUtils.getMediaList(serverItem, null, null, "rtmp",(mediaList ->{
-            Integer code = mediaList.getInteger("code");
-            if (code == 0) {
-                JSONArray data = mediaList.getJSONArray("data");
-                if (data != null) {
-                    zlmServerStatus.put(finalServerItem.getId(),data.size());
-                }else {
-                    zlmServerStatus.put(finalServerItem.getId(),0);
-                }
-
-            }
-        }));
-
     }
     }
 
 
-    /**
-     * 更新缓存
-     * @param mediaServerItem zlm服务
-     * @param count 在线数
-     * @param online 在线状态
-     */
     @Override
     @Override
-    public void updateServerCatch(IMediaServerItem mediaServerItem, Integer count, Boolean online) {
-        if (mediaServerItem != null) {
-            zlmServers.put(mediaServerItem.getId(), mediaServerItem);
-            Collection<Integer> values = zlmServerStatus.values();
-            if (online != null && count != null) {
-                zlmServerStatus.put(mediaServerItem.getId(), count);
-            }
+    public void resetOnlineServerItem(MediaServerItem serverItem) {
+        // 更新缓存
+        String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX;
+        // 使用zset的分数作为当前并发量, 默认值设置为0
+        if (redisUtil.zScore(key, serverItem.getId()) == null) {  // 不存在则设置默认值 已存在则重置
+            redisUtil.zAdd(key, serverItem.getId(), 0L);
+            // 查询服务流数量
+            zlmresTfulUtils.getMediaList(serverItem, null, null, "rtmp",(mediaList ->{
+                Integer code = mediaList.getInteger("code");
+                if (code == 0) {
+                    JSONArray data = mediaList.getJSONArray("data");
+                    if (data != null) {
+                        redisUtil.zAdd(key, serverItem.getId(), data.size());
+                    }
+                }
+            }));
+        }else {
+            clearRTPServer(serverItem);
         }
         }
+
     }
     }
 
 
+
     @Override
     @Override
     public void addCount(String mediaServerId) {
     public void addCount(String mediaServerId) {
-        if (zlmServerStatus.get(mediaServerId) != null) {
-            zlmServerStatus.put(mediaServerId, zlmServerStatus.get(mediaServerId) + 1);
-        }
+        if (mediaServerId == null) return;
+        String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX;
+        Double aDouble = redisUtil.zScore(key, mediaServerId);
+        redisUtil.zIncrScore(key, mediaServerId, 1);
+
     }
     }
 
 
     @Override
     @Override
     public void removeCount(String mediaServerId) {
     public void removeCount(String mediaServerId) {
-        if (zlmServerStatus.get(mediaServerId) != null) {
-            zlmServerStatus.put(mediaServerId, zlmServerStatus.get(mediaServerId) - 1);
-        }
+        String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX;
+        redisUtil.zIncrScore(key, mediaServerId, - 1);
     }
     }
 
 
     /**
     /**
@@ -262,35 +334,18 @@ public class MediaServerServiceImpl implements IMediaServerService {
      * @return MediaServerItem
      * @return MediaServerItem
      */
      */
     @Override
     @Override
-    public IMediaServerItem getMediaServerForMinimumLoad() {
-        int mediaCount = -1;
-        String key = null;
-        System.out.println(JSON.toJSONString(zlmServerStatus));
-        if (zlmServerStatus.size() == 1) {
-            Map.Entry entry = zlmServerStatus.entrySet().iterator().next();
-            key= (String) entry.getKey();
-        }else {
-            for (String id : zlmServerStatus.keySet()) {
-                if (key == null) {
-                    key = id;
-                    mediaCount = zlmServerStatus.get(id);
-                }
-                if (zlmServerStatus.get(id) == 0) {
-                    key = id;
-                    break;
-                }else if (mediaCount >= zlmServerStatus.get(id)){
-                    mediaCount = zlmServerStatus.get(id);
-                    key = id;
-                }
-            }
-        }
+    public MediaServerItem getMediaServerForMinimumLoad() {
+        String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX;
 
 
-        if (key == null) {
+        if (redisUtil.zSize(key)  == null || redisUtil.zSize(key) == 0) {
             logger.info("获取负载最低的节点时无在线节点");
             logger.info("获取负载最低的节点时无在线节点");
-            return null;
-        }else{
-            return  zlmServers.get(key);
         }
         }
+
+        // 获取分数最低的,及并发最低的
+        Set<Object> objects = redisUtil.ZRange(key, 0, -1);
+        ArrayList<Object> MediaServerObjectS = new ArrayList<>(objects);
+        String mediaServerId = (String)MediaServerObjectS.get(0);
+        return getOne(mediaServerId);
     }
     }
 
 
     /**
     /**
@@ -298,7 +353,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
      * @param mediaServerItem 服务ID
      * @param mediaServerItem 服务ID
      */
      */
     @Override
     @Override
-    public void setZLMConfig(IMediaServerItem mediaServerItem) {
+    public void setZLMConfig(MediaServerItem mediaServerItem) {
         logger.info("[ {} ]-[ {}:{} ]设置zlm",
         logger.info("[ {} ]-[ {}:{} ]设置zlm",
                 mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
                 mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
         String protocol = sslEnabled ? "https" : "http";
         String protocol = sslEnabled ? "https" : "http";
@@ -333,8 +388,10 @@ public class MediaServerServiceImpl implements IMediaServerService {
             logger.info("[ {} ]-[ {}:{} ]设置zlm成功",
             logger.info("[ {} ]-[ {}:{} ]设置zlm成功",
                     mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
                     mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
         }else {
         }else {
-            logger.info("[ {} ]-[ {}:{} ]设置zlm失败" + responseJSON.getString("msg"),
+            logger.info("[ {} ]-[ {}:{} ]设置zlm失败",
                     mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
                     mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
         }
         }
     }
     }
+
+
 }
 }

+ 3 - 5
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java

@@ -4,9 +4,7 @@ import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.JSONObject;
 import com.genersoft.iot.vmp.common.StreamInfo;
 import com.genersoft.iot.vmp.common.StreamInfo;
-import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@@ -33,14 +31,14 @@ public class MediaServiceImpl implements IMediaService {
 
 
 
 
     @Override
     @Override
-    public StreamInfo getStreamInfoByAppAndStream(IMediaServerItem mediaInfo, String app, String stream, JSONArray tracks) {
+    public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, JSONArray tracks) {
         return getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, null);
         return getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, null);
     }
     }
 
 
     @Override
     @Override
     public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, String addr) {
     public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, String addr) {
         StreamInfo streamInfo = null;
         StreamInfo streamInfo = null;
-        IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
+        MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
         if (mediaInfo == null) {
         if (mediaInfo == null) {
             return streamInfo;
             return streamInfo;
         }
         }
@@ -63,7 +61,7 @@ public class MediaServiceImpl implements IMediaService {
     }
     }
 
 
     @Override
     @Override
-    public StreamInfo getStreamInfoByAppAndStream(IMediaServerItem mediaInfo, String app, String stream, JSONArray tracks, String addr) {
+    public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, JSONArray tracks, String addr) {
         StreamInfo streamInfoResult = new StreamInfo();
         StreamInfo streamInfoResult = new StreamInfo();
         streamInfoResult.setStreamId(stream);
         streamInfoResult.setStreamId(stream);
         streamInfoResult.setApp(app);
         streamInfoResult.setApp(app);

+ 43 - 22
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java

@@ -14,11 +14,12 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.service.IMediaServerService;
+import com.genersoft.iot.vmp.service.bean.SSRCInfo;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
+import com.genersoft.iot.vmp.utils.redis.RedisUtil;
 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
 import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
 import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
 import com.genersoft.iot.vmp.service.IMediaService;
 import com.genersoft.iot.vmp.service.IMediaService;
@@ -53,6 +54,9 @@ public class PlayServiceImpl implements IPlayService {
     @Autowired
     @Autowired
     private IRedisCatchStorage redisCatchStorage;
     private IRedisCatchStorage redisCatchStorage;
 
 
+    @Autowired
+    private RedisUtil redis;
+
     @Autowired
     @Autowired
     private DeferredResultHolder resultHolder;
     private DeferredResultHolder resultHolder;
 
 
@@ -73,7 +77,7 @@ public class PlayServiceImpl implements IPlayService {
 
 
 
 
     @Override
     @Override
-    public PlayResult play(IMediaServerItem mediaServerItem, String deviceId, String channelId, ZLMHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent) {
+    public PlayResult play(MediaServerItem mediaServerItem, String deviceId, String channelId, ZLMHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent) {
         PlayResult playResult = new PlayResult();
         PlayResult playResult = new PlayResult();
         if (mediaServerItem == null) {
         if (mediaServerItem == null) {
             RequestMessage msg = new RequestMessage();
             RequestMessage msg = new RequestMessage();
@@ -97,14 +101,21 @@ public class PlayServiceImpl implements IPlayService {
         // 超时处理
         // 超时处理
         result.onTimeout(()->{
         result.onTimeout(()->{
             logger.warn(String.format("设备点播超时,deviceId:%s ,channelId:%s", deviceId, channelId));
             logger.warn(String.format("设备点播超时,deviceId:%s ,channelId:%s", deviceId, channelId));
-            // 释放rtpserver
-            mediaServerService.closeRTPServer(playResult.getDevice(), channelId);
             RequestMessage msg = new RequestMessage();
             RequestMessage msg = new RequestMessage();
             msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + playResult.getUuid());
             msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + playResult.getUuid());
             WVPResult wvpResult = new WVPResult();
             WVPResult wvpResult = new WVPResult();
             wvpResult.setCode(-1);
             wvpResult.setCode(-1);
-            wvpResult.setMsg("Timeout");
+            SIPDialog dialog = streamSession.getDialog(deviceId, channelId);
+            if (dialog != null) {
+                wvpResult.setMsg("收流超时,请稍候重试");
+            }else {
+                wvpResult.setMsg("点播超时,请稍候重试");
+            }
             msg.setData(wvpResult);
             msg.setData(wvpResult);
+            // 点播超时回复BYE
+            cmder.streamByeCmd(device.getDeviceId(), channelId);
+            // 释放rtpserver
+            mediaServerService.closeRTPServer(playResult.getDevice(), channelId);
             resultHolder.invokeResult(msg);
             resultHolder.invokeResult(msg);
         });
         });
         result.onCompletion(()->{
         result.onCompletion(()->{
@@ -131,7 +142,7 @@ public class PlayServiceImpl implements IPlayService {
                     WVPResult wvpResult = (WVPResult)responseEntity.getBody();
                     WVPResult wvpResult = (WVPResult)responseEntity.getBody();
                     if (wvpResult.getCode() == 0) {
                     if (wvpResult.getCode() == 0) {
                         StreamInfo streamInfoForSuccess = (StreamInfo)wvpResult.getData();
                         StreamInfo streamInfoForSuccess = (StreamInfo)wvpResult.getData();
-                        IMediaServerItem mediaInfo = mediaServerService.getOne(streamInfoForSuccess.getMediaServerId());
+                        MediaServerItem mediaInfo = mediaServerService.getOne(streamInfoForSuccess.getMediaServerId());
                         String streamUrl = streamInfoForSuccess.getFmp4();
                         String streamUrl = streamInfoForSuccess.getFmp4();
                         // 请求截图
                         // 请求截图
                         zlmresTfulUtils.getSnap(mediaInfo, streamUrl, 15, 1, path, fileName);
                         zlmresTfulUtils.getSnap(mediaInfo, streamUrl, 15, 1, path, fileName);
@@ -142,14 +153,23 @@ public class PlayServiceImpl implements IPlayService {
             }
             }
         });
         });
         if (streamInfo == null) {
         if (streamInfo == null) {
+            SSRCInfo ssrcInfo;
+            String streamId = null;
+            if (mediaServerItem.isRtpEnable()) {
+                streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
+            }
+
+            ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId);
+
             // 发送点播消息
             // 发送点播消息
-            cmder.playStreamCmd(mediaServerItem, device, channelId, (IMediaServerItem mediaServerItemInUse, JSONObject response) -> {
+            cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInUse, JSONObject response) -> {
                 logger.info("收到订阅消息: " + response.toJSONString());
                 logger.info("收到订阅消息: " + response.toJSONString());
                 onPublishHandlerForPlay(mediaServerItemInUse, response, deviceId, channelId, uuid.toString());
                 onPublishHandlerForPlay(mediaServerItemInUse, response, deviceId, channelId, uuid.toString());
                 if (hookEvent != null) {
                 if (hookEvent != null) {
                     hookEvent.response(mediaServerItem, response);
                     hookEvent.response(mediaServerItem, response);
                 }
                 }
             }, (event) -> {
             }, (event) -> {
+                // 点播返回sip错误
                 RequestMessage msg = new RequestMessage();
                 RequestMessage msg = new RequestMessage();
                 msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
                 msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
                 Response response = event.getResponse();
                 Response response = event.getResponse();
@@ -162,6 +182,7 @@ public class PlayServiceImpl implements IPlayService {
                 if (errorEvent != null) {
                 if (errorEvent != null) {
                     errorEvent.response(event);
                     errorEvent.response(event);
                 }
                 }
+
             });
             });
         } else {
         } else {
             String streamId = streamInfo.getStreamId();
             String streamId = streamInfo.getStreamId();
@@ -176,7 +197,7 @@ public class PlayServiceImpl implements IPlayService {
                 return playResult;
                 return playResult;
             }
             }
             String mediaServerId = streamInfo.getMediaServerId();
             String mediaServerId = streamInfo.getMediaServerId();
-            IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
+            MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
 
 
             JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId);
             JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId);
             if (rtpInfo != null && rtpInfo.getBoolean("exist")) {
             if (rtpInfo != null && rtpInfo.getBoolean("exist")) {
@@ -194,9 +215,17 @@ public class PlayServiceImpl implements IPlayService {
                     hookEvent.response(mediaServerItem, JSONObject.parseObject(JSON.toJSONString(streamInfo)));
                     hookEvent.response(mediaServerItem, JSONObject.parseObject(JSON.toJSONString(streamInfo)));
                 }
                 }
             } else {
             } else {
+                // TODO 点播前是否重置状态
                 redisCatchStorage.stopPlay(streamInfo);
                 redisCatchStorage.stopPlay(streamInfo);
                 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
                 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
-                cmder.playStreamCmd(mediaServerItem, device, channelId, (IMediaServerItem mediaServerItemInuse, JSONObject response) -> {
+                SSRCInfo ssrcInfo;
+                String streamId2 = null;
+                if (mediaServerItem.isRtpEnable()) {
+                    streamId2 = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
+                }
+                ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId2);
+
+                cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> {
                     logger.info("收到订阅消息: " + response.toJSONString());
                     logger.info("收到订阅消息: " + response.toJSONString());
                     onPublishHandlerForPlay(mediaServerItemInuse, response, deviceId, channelId, uuid.toString());
                     onPublishHandlerForPlay(mediaServerItemInuse, response, deviceId, channelId, uuid.toString());
                 }, (event) -> {
                 }, (event) -> {
@@ -218,7 +247,7 @@ public class PlayServiceImpl implements IPlayService {
     }
     }
 
 
     @Override
     @Override
-    public void onPublishHandlerForPlay(IMediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) {
+    public void onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) {
         RequestMessage msg = new RequestMessage();
         RequestMessage msg = new RequestMessage();
         msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
         msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
         StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid);
         StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid);
@@ -228,14 +257,6 @@ public class PlayServiceImpl implements IPlayService {
                 deviceChannel.setStreamId(streamInfo.getStreamId());
                 deviceChannel.setStreamId(streamInfo.getStreamId());
                 storager.startPlay(deviceId, channelId, streamInfo.getStreamId());
                 storager.startPlay(deviceId, channelId, streamInfo.getStreamId());
             }
             }
-            ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId);
-            SIPDialog dialog = (SIPDialog)transaction.getDialog();
-            StreamInfo.TransactionInfo transactionInfo = new StreamInfo.TransactionInfo();
-            transactionInfo.callId = dialog.getCallId().getCallId();
-            transactionInfo.localTag = dialog.getLocalTag();
-            transactionInfo.remoteTag = dialog.getRemoteTag();
-            transactionInfo.branch = dialog.getFirstTransactionInt().getBranchId();
-            streamInfo.setTransactionInfo(transactionInfo);
             redisCatchStorage.startPlay(streamInfo);
             redisCatchStorage.startPlay(streamInfo);
             msg.setData(JSON.toJSONString(streamInfo));
             msg.setData(JSON.toJSONString(streamInfo));
 
 
@@ -254,10 +275,10 @@ public class PlayServiceImpl implements IPlayService {
     }
     }
 
 
     @Override
     @Override
-    public IMediaServerItem getNewMediaServerItem(Device device) {
+    public MediaServerItem getNewMediaServerItem(Device device) {
         if (device == null) return null;
         if (device == null) return null;
         String mediaServerId = device.getMediaServerId();
         String mediaServerId = device.getMediaServerId();
-        IMediaServerItem mediaServerItem = null;
+        MediaServerItem mediaServerItem = null;
         if (mediaServerId == null) {
         if (mediaServerId == null) {
             mediaServerItem = mediaServerService.getMediaServerForMinimumLoad();
             mediaServerItem = mediaServerService.getMediaServerForMinimumLoad();
         }else {
         }else {
@@ -270,7 +291,7 @@ public class PlayServiceImpl implements IPlayService {
     }
     }
 
 
     @Override
     @Override
-    public void onPublishHandlerForPlayBack(IMediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) {
+    public void onPublishHandlerForPlayBack(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) {
         RequestMessage msg = new RequestMessage();
         RequestMessage msg = new RequestMessage();
         msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
         msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
         StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid);
         StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid);
@@ -285,7 +306,7 @@ public class PlayServiceImpl implements IPlayService {
         }
         }
     }
     }
 
 
-    public StreamInfo onPublishHandler(IMediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) {
+    public StreamInfo onPublishHandler(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) {
         String streamId = resonse.getString("stream");
         String streamId = resonse.getString("stream");
         JSONArray tracks = resonse.getJSONArray("tracks");
         JSONArray tracks = resonse.getJSONArray("tracks");
         StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem,"rtp", streamId, tracks);
         StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem,"rtp", streamId, tracks);

+ 4 - 5
src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java

@@ -3,7 +3,6 @@ package com.genersoft.iot.vmp.service.impl;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.JSONObject;
 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
 import com.genersoft.iot.vmp.service.IGbStreamService;
 import com.genersoft.iot.vmp.service.IGbStreamService;
@@ -58,7 +57,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
 
 
     @Override
     @Override
     public String save(StreamProxyItem param) {
     public String save(StreamProxyItem param) {
-        IMediaServerItem mediaInfo;
+        MediaServerItem mediaInfo;
         if ("auto".equals(param.getMediaServerId())){
         if ("auto".equals(param.getMediaServerId())){
             mediaInfo = mediaServerService.getMediaServerForMinimumLoad();
             mediaInfo = mediaServerService.getMediaServerForMinimumLoad();
         }else {
         }else {
@@ -120,7 +119,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
     @Override
     @Override
     public JSONObject addStreamProxyToZlm(StreamProxyItem param) {
     public JSONObject addStreamProxyToZlm(StreamProxyItem param) {
         JSONObject result = null;
         JSONObject result = null;
-        IMediaServerItem mediaServerItem = null;
+        MediaServerItem mediaServerItem = null;
         if (param.getMediaServerId() == null) {
         if (param.getMediaServerId() == null) {
             logger.warn("添加代理时MediaServerId 为null");
             logger.warn("添加代理时MediaServerId 为null");
             return null;
             return null;
@@ -141,7 +140,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
     @Override
     @Override
     public JSONObject removeStreamProxyFromZlm(StreamProxyItem param) {
     public JSONObject removeStreamProxyFromZlm(StreamProxyItem param) {
         if (param ==null) return null;
         if (param ==null) return null;
-        IMediaServerItem mediaServerItem = mediaServerService.getOne(param.getMediaServerId());
+        MediaServerItem mediaServerItem = mediaServerService.getOne(param.getMediaServerId());
         JSONObject result = zlmresTfulUtils.closeStreams(mediaServerItem, param.getApp(), param.getStream());
         JSONObject result = zlmresTfulUtils.closeStreams(mediaServerItem, param.getApp(), param.getStream());
         return result;
         return result;
     }
     }
@@ -198,7 +197,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
     }
     }
 
 
     @Override
     @Override
-    public JSONObject getFFmpegCMDs(IMediaServerItem mediaServerItem) {
+    public JSONObject getFFmpegCMDs(MediaServerItem mediaServerItem) {
         JSONObject result = new JSONObject();
         JSONObject result = new JSONObject();
         JSONObject mediaServerConfigResuly = zlmresTfulUtils.getMediaServerConfig(mediaServerItem);
         JSONObject mediaServerConfigResuly = zlmresTfulUtils.getMediaServerConfig(mediaServerItem);
         if (mediaServerConfigResuly != null && mediaServerConfigResuly.getInteger("code") == 0
         if (mediaServerConfigResuly != null && mediaServerConfigResuly.getInteger("code") == 0

+ 2 - 3
src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java

@@ -5,7 +5,6 @@ import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.TypeReference;
 import com.alibaba.fastjson.TypeReference;
 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
@@ -43,7 +42,7 @@ public class StreamPushServiceImpl implements IStreamPushService {
     private IMediaServerService mediaServerService;
     private IMediaServerService mediaServerService;
 
 
     @Override
     @Override
-    public List<StreamPushItem> handleJSON(String jsonData, IMediaServerItem mediaServerItem) {
+    public List<StreamPushItem> handleJSON(String jsonData, MediaServerItem mediaServerItem) {
         if (jsonData == null) return null;
         if (jsonData == null) return null;
 
 
         Map<String, StreamPushItem> result = new HashMap<>();
         Map<String, StreamPushItem> result = new HashMap<>();
@@ -98,7 +97,7 @@ public class StreamPushServiceImpl implements IStreamPushService {
     @Override
     @Override
     public boolean removeFromGB(GbStream stream) {
     public boolean removeFromGB(GbStream stream) {
         int del = gbStreamMapper.del(stream.getApp(), stream.getStream());
         int del = gbStreamMapper.del(stream.getApp(), stream.getStream());
-        IMediaServerItem mediaInfo = mediaServerService.getOne(stream.getMediaServerId());
+        MediaServerItem mediaInfo = mediaServerService.getOne(stream.getMediaServerId());
         JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaInfo, stream.getApp(), stream.getStream());
         JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaInfo, stream.getApp(), stream.getStream());
         if (mediaList == null) {
         if (mediaList == null) {
             streamPushMapper.del(stream.getApp(), stream.getStream());
             streamPushMapper.del(stream.getApp(), stream.getStream());

+ 0 - 2
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java

@@ -5,8 +5,6 @@ import com.genersoft.iot.vmp.common.StreamInfo;
 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
-import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 
 
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;

+ 0 - 1
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java

@@ -3,7 +3,6 @@ package com.genersoft.iot.vmp.storager;
 import java.util.List;
 import java.util.List;
 
 
 import com.genersoft.iot.vmp.gb28181.bean.*;
 import com.genersoft.iot.vmp.gb28181.bean.*;
-import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;

+ 5 - 5
src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java

@@ -1,7 +1,5 @@
 package com.genersoft.iot.vmp.storager.dao;
 package com.genersoft.iot.vmp.storager.dao;
 
 
-import com.genersoft.iot.vmp.conf.MediaConfig;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import org.apache.ibatis.annotations.Insert;
 import org.apache.ibatis.annotations.Insert;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Mapper;
@@ -35,6 +33,7 @@ public interface MediaServerMapper {
             "rtpEnable, " +
             "rtpEnable, " +
             "rtpPortRange, " +
             "rtpPortRange, " +
             "recordAssistPort, " +
             "recordAssistPort, " +
+            "defaultServer, " +
             "createTime, " +
             "createTime, " +
             "updateTime" +
             "updateTime" +
             ") VALUES " +
             ") VALUES " +
@@ -57,9 +56,10 @@ public interface MediaServerMapper {
             "${rtpEnable}, " +
             "${rtpEnable}, " +
             "'${rtpPortRange}', " +
             "'${rtpPortRange}', " +
             "${recordAssistPort}, " +
             "${recordAssistPort}, " +
+            "${defaultServer}, " +
             "'${createTime}', " +
             "'${createTime}', " +
             "'${updateTime}')")
             "'${updateTime}')")
-    int add(IMediaServerItem mediaServerItem);
+    int add(MediaServerItem mediaServerItem);
 
 
     @Update(value = {" <script>" +
     @Update(value = {" <script>" +
             "UPDATE media_server " +
             "UPDATE media_server " +
@@ -83,7 +83,7 @@ public interface MediaServerMapper {
             "<if test=\"recordAssistPort != null\">, recordAssistPort=${recordAssistPort}</if>" +
             "<if test=\"recordAssistPort != null\">, recordAssistPort=${recordAssistPort}</if>" +
             "WHERE id='${id}'"+
             "WHERE id='${id}'"+
             " </script>"})
             " </script>"})
-    int update(IMediaServerItem mediaServerItem);
+    int update(MediaServerItem mediaServerItem);
 
 
     @Select("SELECT * FROM media_server WHERE id='${id}'")
     @Select("SELECT * FROM media_server WHERE id='${id}'")
     MediaServerItem queryOne(String id);
     MediaServerItem queryOne(String id);
@@ -92,7 +92,7 @@ public interface MediaServerMapper {
     List<MediaServerItem> queryAll();
     List<MediaServerItem> queryAll();
 
 
     @Select("DELETE FROM media_server WHERE id='${id}'")
     @Select("DELETE FROM media_server WHERE id='${id}'")
-    int delOne(String secret);
+    void delOne(String id);
 
 
     @Select("SELECT * FROM media_server WHERE ip='${host}' and httpPort=${port}")
     @Select("SELECT * FROM media_server WHERE ip='${host}' and httpPort=${port}")
     MediaServerItem queryOneByHostAndPort(String host, int port);
     MediaServerItem queryOneByHostAndPort(String host, int port);

+ 0 - 3
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java

@@ -3,10 +3,7 @@ package com.genersoft.iot.vmp.storager.impl;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.JSONObject;
 import com.genersoft.iot.vmp.common.StreamInfo;
 import com.genersoft.iot.vmp.common.StreamInfo;
 import com.genersoft.iot.vmp.common.VideoManagerConstants;
 import com.genersoft.iot.vmp.common.VideoManagerConstants;
-import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
 import com.genersoft.iot.vmp.gb28181.bean.*;
 import com.genersoft.iot.vmp.gb28181.bean.*;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
-import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
 import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
 import com.genersoft.iot.vmp.utils.redis.RedisUtil;
 import com.genersoft.iot.vmp.utils.redis.RedisUtil;

+ 8 - 0
src/main/java/com/genersoft/iot/vmp/utils/ConfigConst.java

@@ -0,0 +1,8 @@
+package com.genersoft.iot.vmp.utils;
+
+public class ConfigConst {
+    /**
+     * 播流最大并发个数
+     */
+    public static final Integer MAX_STRTEAM_COUNT = 10000;
+}

+ 31 - 0
src/main/java/com/genersoft/iot/vmp/utils/SerializeUtils.java

@@ -0,0 +1,31 @@
+package com.genersoft.iot.vmp.utils;
+
+import java.io.*;
+
+public class SerializeUtils {
+    public static byte[] serialize(Object obj){
+        byte[] bytes = null;
+        try {
+            ByteArrayOutputStream baos=new ByteArrayOutputStream();;
+            ObjectOutputStream oos=new ObjectOutputStream(baos);
+            oos.writeObject(obj);
+            bytes=baos.toByteArray();
+            baos.close();
+            oos.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return bytes;
+    }
+    public static Object deSerialize(byte[] bytes){
+        Object obj=null;
+        try {
+            ByteArrayInputStream bais=new ByteArrayInputStream(bytes);
+            ObjectInputStream ois=new ObjectInputStream(bais);
+            obj=ois.readObject();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return obj;
+    }
+}

+ 97 - 0
src/main/java/com/genersoft/iot/vmp/utils/redis/JedisUtil.java

@@ -0,0 +1,97 @@
+package com.genersoft.iot.vmp.utils.redis;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.JedisPool;
+
+import java.util.Set;
+
+/**
+ * @Description:Jedis工具类
+ * @author: wangshaopeng@sunnybs.com
+ * @date: 2021年03月22日 下午8:27:29
+ */
+@Component
+public class JedisUtil {
+
+    @Autowired
+    private JedisPool jedisPool;
+
+    //    ============================== Key ==============================
+
+    /**
+     * 检查给定 key 是否存在。
+     *
+     * @param key
+     * @return
+     */
+    public Boolean exists(String key) {
+        Jedis jedis = null;
+        try {
+            jedis = jedisPool.getResource();
+            Boolean exists = jedis.exists(key);
+            return exists;
+        } finally {
+            returnToPool(jedis);
+        }
+    }
+
+
+    //    ============================== Set ==============================
+
+    /**
+     * SADD key member [member ...]
+     * 将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略。
+     * 假如 key 不存在,则创建一个只包含 member 元素作成员的集合。
+     * 当 key 不是集合类型时,返回一个错误。
+     */
+    public Long sadd(String key, String... members) {
+        Jedis jedis = null;
+        try {
+            jedis = jedisPool.getResource();
+            Long smove = jedis.sadd(key, members);
+            return smove;
+        } finally {
+            returnToPool(jedis);
+        }
+    }
+
+    /**
+     * SMEMBERS key
+     * 返回集合 key 中的所有成员。
+     * 不存在的 key 被视为空集合。
+     */
+    public Set<String> smembers(String key) {
+        Jedis jedis = null;
+        try {
+            jedis = jedisPool.getResource();
+            Set<String> smembers = jedis.smembers(key);
+            return smembers;
+        } finally {
+            returnToPool(jedis);
+        }
+    }
+
+
+    /**
+     * SREM key member1 [member2]
+     * 移除集合中一个或多个成员
+     */
+    public Long srem(String key, String... member) {
+        Jedis jedis = null;
+        try {
+            jedis = jedisPool.getResource();
+            Long srem = jedis.srem(key, member);
+            return srem;
+        } finally {
+            returnToPool(jedis);
+        }
+    }
+
+    private void returnToPool(Jedis jedis) {
+        if (jedis != null) {
+            jedis.close();
+        }
+    }
+}

+ 3 - 3
src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java

@@ -415,10 +415,10 @@ public class RedisUtil {
      *
      *
      * @param key
      * @param key
      * @param value
      * @param value
-     * @param score
+     * @param delta -1 表示减 1 表示加1
      */
      */
-    public Double zIncrScore(Object key, Object value, double score) {
-        return redisTemplate.opsForZSet().incrementScore(key, value, score);
+    public Double zIncrScore(Object key, Object value, double delta) {
+        return redisTemplate.opsForZSet().incrementScore(key, value, delta);
     }
     }
 
 
     /**
     /**

+ 12 - 13
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java

@@ -2,13 +2,12 @@ package com.genersoft.iot.vmp.vmanager.gb28181.play;
 
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONArray;
 import com.genersoft.iot.vmp.common.StreamInfo;
 import com.genersoft.iot.vmp.common.StreamInfo;
+import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
-import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
 import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@@ -37,7 +36,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
 import org.springframework.web.context.request.async.DeferredResult;
 import org.springframework.web.context.request.async.DeferredResult;
 
 
-import java.util.Enumeration;
+import java.util.List;
 import java.util.Map;
 import java.util.Map;
 import java.util.UUID;
 import java.util.UUID;
 
 
@@ -89,7 +88,7 @@ public class PlayController {
 
 
 		// 获取可用的zlm
 		// 获取可用的zlm
 		Device device = storager.queryVideoDevice(deviceId);
 		Device device = storager.queryVideoDevice(deviceId);
-		IMediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
+		MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
 		PlayResult playResult = playService.play(newMediaServerItem, deviceId, channelId, null, null);
 		PlayResult playResult = playService.play(newMediaServerItem, deviceId, channelId, null, null);
 
 
 		return playResult.getResult();
 		return playResult.getResult();
@@ -174,7 +173,7 @@ public class PlayController {
 			logger.warn("视频转码API调用失败!, 视频流已经停止!");
 			logger.warn("视频转码API调用失败!, 视频流已经停止!");
 			return new ResponseEntity<String>("未找到视频流信息, 视频流可能已经停止", HttpStatus.OK);
 			return new ResponseEntity<String>("未找到视频流信息, 视频流可能已经停止", HttpStatus.OK);
 		}
 		}
-		IMediaServerItem mediaInfo = mediaServerService.getOne(streamInfo.getMediaServerId());
+		MediaServerItem mediaInfo = mediaServerService.getOne(streamInfo.getMediaServerId());
 		JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId);
 		JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId);
 		if (!rtpInfo.getBoolean("exist")) {
 		if (!rtpInfo.getBoolean("exist")) {
 			logger.warn("视频转码API调用失败!, 视频流已停止推流!");
 			logger.warn("视频转码API调用失败!, 视频流已停止推流!");
@@ -219,7 +218,7 @@ public class PlayController {
 			result.put("msg", "mediaServerId is null");
 			result.put("msg", "mediaServerId is null");
 			return new ResponseEntity<String>( result.toJSONString(), HttpStatus.BAD_REQUEST);
 			return new ResponseEntity<String>( result.toJSONString(), HttpStatus.BAD_REQUEST);
 		}
 		}
-		IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
+		MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
 		if (mediaInfo == null) {
 		if (mediaInfo == null) {
 			result.put("code", 0);
 			result.put("code", 0);
 			result.put("msg", "使用的流媒体已经停止运行");
 			result.put("msg", "使用的流媒体已经停止运行");
@@ -307,16 +306,16 @@ public class PlayController {
 			logger.debug("获取所有的ssrc");
 			logger.debug("获取所有的ssrc");
 		}
 		}
 		JSONArray objects = new JSONArray();
 		JSONArray objects = new JSONArray();
-		for(Map.Entry<String, String> entry: streamSession.getSsrcMap().entrySet()) {
-			System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
+		List<SsrcTransaction> allSsrc = streamSession.getAllSsrc();
+		for (SsrcTransaction transaction : allSsrc) {
 			JSONObject jsonObject = new JSONObject();
 			JSONObject jsonObject = new JSONObject();
-			String[] keyArray = entry.getKey().split("_");
-			jsonObject.put("deviceId", keyArray[0]);
-			jsonObject.put("channelId", keyArray[1]);
-			jsonObject.put("ssrc", entry.getValue());
-			jsonObject.put("streamId", streamSession.getStreamIdMap().get(entry.getKey()));
+			jsonObject.put("deviceId", transaction.getDeviceId());
+			jsonObject.put("channelId", transaction.getChannelId());
+			jsonObject.put("ssrc", transaction.getSsrc());
+			jsonObject.put("streamId", transaction.getStreamId());
 			objects.add(jsonObject);
 			objects.add(jsonObject);
 		}
 		}
+
 		WVPResult<JSONObject> result = new WVPResult<>();
 		WVPResult<JSONObject> result = new WVPResult<>();
 		result.setCode(0);
 		result.setCode(0);
 		result.setMsg("success");
 		result.setMsg("success");

+ 10 - 4
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java

@@ -3,9 +3,9 @@ package com.genersoft.iot.vmp.vmanager.gb28181.playback;
 import com.genersoft.iot.vmp.common.StreamInfo;
 import com.genersoft.iot.vmp.common.StreamInfo;
 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
-//import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
+import com.genersoft.iot.vmp.service.IMediaServerService;
+import com.genersoft.iot.vmp.service.bean.SSRCInfo;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.service.IPlayService;
 import com.genersoft.iot.vmp.service.IPlayService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.Api;
@@ -58,6 +58,9 @@ public class DownloadController {
 	@Autowired
 	@Autowired
 	private DeferredResultHolder resultHolder;
 	private DeferredResultHolder resultHolder;
 
 
+	@Autowired
+	private IMediaServerService mediaServerService;
+
 	@ApiOperation("开始历史媒体下载")
 	@ApiOperation("开始历史媒体下载")
 	@ApiImplicitParams({
 	@ApiImplicitParams({
 			@ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class),
 			@ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class),
@@ -90,7 +93,7 @@ public class DownloadController {
 			cmder.streamByeCmd(deviceId, channelId);
 			cmder.streamByeCmd(deviceId, channelId);
 		}
 		}
 		resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result);
 		resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result);
-		IMediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
+		MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
 		if (newMediaServerItem == null) {
 		if (newMediaServerItem == null) {
 			logger.warn(String.format("设备下载响应超时,deviceId:%s ,channelId:%s", deviceId, channelId));
 			logger.warn(String.format("设备下载响应超时,deviceId:%s ,channelId:%s", deviceId, channelId));
 			RequestMessage msg = new RequestMessage();
 			RequestMessage msg = new RequestMessage();
@@ -99,7 +102,10 @@ public class DownloadController {
 			resultHolder.invokeResult(msg);
 			resultHolder.invokeResult(msg);
 			return result;
 			return result;
 		}
 		}
-		cmder.downloadStreamCmd(newMediaServerItem, device, channelId, startTime, endTime, downloadSpeed, (IMediaServerItem mediaServerItem, JSONObject response) -> {
+
+		SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null);
+
+		cmder.downloadStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, (MediaServerItem mediaServerItem, JSONObject response) -> {
 			logger.info("收到订阅消息: " + response.toJSONString());
 			logger.info("收到订阅消息: " + response.toJSONString());
 			playService.onPublishHandlerForPlayBack(mediaServerItem, response, deviceId, channelId, uuid.toString());
 			playService.onPublishHandlerForPlayBack(mediaServerItem, response, deviceId, channelId, uuid.toString());
 		}, event -> {
 		}, event -> {

+ 18 - 4
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java

@@ -4,8 +4,9 @@ import com.genersoft.iot.vmp.common.StreamInfo;
 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
 //import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
 //import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
+import com.genersoft.iot.vmp.service.IMediaServerService;
+import com.genersoft.iot.vmp.service.bean.SSRCInfo;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.service.IPlayService;
 import com.genersoft.iot.vmp.service.IPlayService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.Api;
@@ -58,6 +59,9 @@ public class PlaybackController {
 	@Autowired
 	@Autowired
 	private DeferredResultHolder resultHolder;
 	private DeferredResultHolder resultHolder;
 
 
+	@Autowired
+	private IMediaServerService mediaServerService;
+
 	@ApiOperation("开始视频回放")
 	@ApiOperation("开始视频回放")
 	@ApiImplicitParams({
 	@ApiImplicitParams({
 			@ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class),
 			@ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class),
@@ -74,6 +78,15 @@ public class PlaybackController {
 		}
 		}
 		UUID uuid = UUID.randomUUID();
 		UUID uuid = UUID.randomUUID();
 		DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(30000L);
 		DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(30000L);
+
+		Device device = storager.queryVideoDevice(deviceId);
+		if (device == null) {
+			result.setResult(new ResponseEntity<>(HttpStatus.BAD_REQUEST));
+			return result;
+		}
+		MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
+		SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null);
+
 		// 超时处理
 		// 超时处理
 		result.onTimeout(()->{
 		result.onTimeout(()->{
 			logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId));
 			logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId));
@@ -82,14 +95,14 @@ public class PlaybackController {
 			msg.setData("Timeout");
 			msg.setData("Timeout");
 			resultHolder.invokeResult(msg);
 			resultHolder.invokeResult(msg);
 		});
 		});
-		Device device = storager.queryVideoDevice(deviceId);
+
 		StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, channelId);
 		StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, channelId);
 		if (streamInfo != null) {
 		if (streamInfo != null) {
 			// 停止之前的回放
 			// 停止之前的回放
 			cmder.streamByeCmd(deviceId, channelId);
 			cmder.streamByeCmd(deviceId, channelId);
 		}
 		}
 		resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result);
 		resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result);
-		IMediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
+
 		if (newMediaServerItem == null) {
 		if (newMediaServerItem == null) {
 			logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId));
 			logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId));
 			RequestMessage msg = new RequestMessage();
 			RequestMessage msg = new RequestMessage();
@@ -98,7 +111,8 @@ public class PlaybackController {
 			resultHolder.invokeResult(msg);
 			resultHolder.invokeResult(msg);
 			return result;
 			return result;
 		}
 		}
-		cmder.playbackStreamCmd(newMediaServerItem, device, channelId, startTime, endTime, (IMediaServerItem mediaServerItem, JSONObject response) -> {
+
+		cmder.playbackStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, (MediaServerItem mediaServerItem, JSONObject response) -> {
 			logger.info("收到订阅消息: " + response.toJSONString());
 			logger.info("收到订阅消息: " + response.toJSONString());
 			playService.onPublishHandlerForPlayBack(mediaServerItem, response, deviceId, channelId, uuid.toString());
 			playService.onPublishHandlerForPlayBack(mediaServerItem, response, deviceId, channelId, uuid.toString());
 		}, event -> {
 		}, event -> {

+ 23 - 0
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/session/PlayTypeEnum.java

@@ -0,0 +1,23 @@
+package com.genersoft.iot.vmp.vmanager.gb28181.session;
+
+public enum PlayTypeEnum {
+
+    PLAY("0", "直播"),
+    PLAY_BACK("1", "回放");
+
+    private String value;
+    private String name;
+
+    PlayTypeEnum(String value, String name) {
+        this.value = value;
+        this.name = name;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public String getName() {
+        return name;
+    }
+}

+ 16 - 8
src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java

@@ -1,10 +1,8 @@
 package com.genersoft.iot.vmp.vmanager.server;
 package com.genersoft.iot.vmp.vmanager.server;
 
 
 import com.genersoft.iot.vmp.VManageBootstrap;
 import com.genersoft.iot.vmp.VManageBootstrap;
-import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
+import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.service.IMediaServerService;
-import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.utils.SpringBeanFactory;
 import com.genersoft.iot.vmp.utils.SpringBeanFactory;
 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
 import gov.nist.javax.sip.SipStackImpl;
 import gov.nist.javax.sip.SipStackImpl;
@@ -17,7 +15,6 @@ import org.springframework.web.bind.annotation.*;
 import javax.sip.ListeningPoint;
 import javax.sip.ListeningPoint;
 import javax.sip.ObjectInUseException;
 import javax.sip.ObjectInUseException;
 import javax.sip.SipProvider;
 import javax.sip.SipProvider;
-import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.Iterator;
 import java.util.List;
 import java.util.List;
 
 
@@ -38,19 +35,30 @@ public class ServerController {
     @ApiOperation("流媒体服务列表")
     @ApiOperation("流媒体服务列表")
     @GetMapping(value = "/media_server/list")
     @GetMapping(value = "/media_server/list")
     @ResponseBody
     @ResponseBody
-    public WVPResult<List<IMediaServerItem>> getMediaServerList(){
-        WVPResult<List<IMediaServerItem>> result = new WVPResult<>();
+    public WVPResult<List<MediaServerItem>> getMediaServerList(){
+        WVPResult<List<MediaServerItem>> result = new WVPResult<>();
         result.setCode(0);
         result.setCode(0);
         result.setMsg("success");
         result.setMsg("success");
         result.setData(mediaServerService.getAll());
         result.setData(mediaServerService.getAll());
         return result;
         return result;
     }
     }
 
 
+    @ApiOperation("在线流媒体服务列表")
+    @GetMapping(value = "/media_server/online/list")
+    @ResponseBody
+    public WVPResult<List<MediaServerItem>> getOnlineMediaServerList(){
+        WVPResult<List<MediaServerItem>> result = new WVPResult<>();
+        result.setCode(0);
+        result.setMsg("success");
+        result.setData(mediaServerService.getAllOnline());
+        return result;
+    }
+
     @ApiOperation("获取流媒体服务")
     @ApiOperation("获取流媒体服务")
     @GetMapping(value = "/media_server/one/{id}")
     @GetMapping(value = "/media_server/one/{id}")
     @ResponseBody
     @ResponseBody
-    public WVPResult<IMediaServerItem> getMediaServer(@PathVariable String id){
-        WVPResult<IMediaServerItem> result = new WVPResult<>();
+    public WVPResult<MediaServerItem> getMediaServer(@PathVariable String id){
+        WVPResult<MediaServerItem> result = new WVPResult<>();
         result.setCode(0);
         result.setCode(0);
         result.setMsg("success");
         result.setMsg("success");
         result.setData(mediaServerService.getOne(id));
         result.setData(mediaServerService.getOne(id));

+ 1 - 3
src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java

@@ -1,7 +1,6 @@
 package com.genersoft.iot.vmp.vmanager.streamProxy;
 package com.genersoft.iot.vmp.vmanager.streamProxy;
 
 
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.JSONObject;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.service.IMediaServerService;
@@ -9,7 +8,6 @@ import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.service.IStreamProxyService;
 import com.genersoft.iot.vmp.service.IStreamProxyService;
 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
 import com.github.pagehelper.PageInfo;
 import com.github.pagehelper.PageInfo;
-import io.netty.util.internal.StringUtil;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiImplicitParams;
@@ -86,7 +84,7 @@ public class StreamProxyController {
     public WVPResult getFFmpegCMDs(@RequestParam String mediaServerId){
     public WVPResult getFFmpegCMDs(@RequestParam String mediaServerId){
         logger.debug("获取节点[ {} ]ffmpeg.cmd模板", mediaServerId );
         logger.debug("获取节点[ {} ]ffmpeg.cmd模板", mediaServerId );
 
 
-        IMediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
+        MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
         JSONObject data = streamProxyService.getFFmpegCMDs(mediaServerItem);
         JSONObject data = streamProxyService.getFFmpegCMDs(mediaServerItem);
         WVPResult<JSONObject> result = new WVPResult<>();
         WVPResult<JSONObject> result = new WVPResult<>();
         result.setCode(0);
         result.setCode(0);

+ 7 - 0
src/main/resources/all-application.yml

@@ -17,6 +17,12 @@ spring:
         password:
         password:
         # [可选] 超时时间
         # [可选] 超时时间
         timeout: 10000
         timeout: 10000
+        # [可选] 一个pool最多可分配多少个jedis实例
+        poolMaxTotal: 1000
+        # [可选] 一个pool最多有多少个状态为idle(空闲)的jedis实例
+        poolMaxIdle: 500
+        # [可选] 最大的等待时间(秒)
+        poolMaxWait: 5
     # [可选] jdbc数据库配置, 项目使用sqlite作为数据库,一般不需要配置
     # [可选] jdbc数据库配置, 项目使用sqlite作为数据库,一般不需要配置
     datasource:
     datasource:
         # 使用mysql 打开23-28行注释, 删除29-36行
         # 使用mysql 打开23-28行注释, 删除29-36行
@@ -124,6 +130,7 @@ logging:
     level:
     level:
         com.genersoft.iot: debug
         com.genersoft.iot: debug
         com.genersoft.iot.vmp.storager.dao: info
         com.genersoft.iot.vmp.storager.dao: info
+        com.genersoft.iot.vmp.gb28181: info
 # [根据业务需求配置]
 # [根据业务需求配置]
 user-settings:
 user-settings:
     # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
     # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true

+ 2 - 0
src/main/resources/application-dev.yml

@@ -76,6 +76,8 @@ logging:
     level:
     level:
         com.genersoft.iot: debug
         com.genersoft.iot: debug
         com.genersoft.iot.vmp.storager.dao: info
         com.genersoft.iot.vmp.storager.dao: info
+        com.genersoft.iot.vmp.gb28181: info
+
 # [根据业务需求配置]
 # [根据业务需求配置]
 user-settings:
 user-settings:
     # 推流直播是否录制
     # 推流直播是否录制

BIN
src/main/resources/wvp.sqlite


+ 1 - 1
web_src/src/components/service/MediaServer.js

@@ -9,7 +9,7 @@ class MediaServer{
   getMediaServerList(callback){
   getMediaServerList(callback){
     this.$axios({
     this.$axios({
       method: 'get',
       method: 'get',
-      url:`/api/server/media_server/list`,
+      url:`/api/server/media_server/online/list`,
     }).then(function (res) {
     }).then(function (res) {
       if (typeof (callback) == "function") callback(res.data)
       if (typeof (callback) == "function") callback(res.data)
     }).catch(function (error) {
     }).catch(function (error) {