From 3469271ec25c69e4528b085ba3be7d9d85ec519e Mon Sep 17 00:00:00 2001
From: 64850858 <648540858@qq.com>
Date: 星期一, 26 七月 2021 11:40:32 +0800
Subject: [PATCH] 优化集群方案, 每个zlm一套ssrc; 优化集群下的docker接入逻辑; 更正sql脚本; 支持重启不设置设备离线。重启SIP事务不丢失

---
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/InviteResponseProcessor.java           |   14 
 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/session/PlayTypeEnum.java                            |   23 
 web_src/src/components/service/MediaServer.js                                                             |    2 
 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java                                    |   80 +-
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java                               |   10 
 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java                     |   14 
 sql/mysql.sql                                                                                             |  204 ++--
 src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java                                      |    2 
 src/main/java/com/genersoft/iot/vmp/utils/redis/JedisUtil.java                                            |   97 ++
 src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java                              |  391 +++++----
 src/main/resources/application-dev.yml                                                                    |    2 
 src/main/java/com/genersoft/iot/vmp/service/IPlayService.java                                             |    9 
 src/main/java/com/genersoft/iot/vmp/service/bean/SSRCInfo.java                                            |   38 +
 src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java                                     |   65 +
 src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java                                                 |   37 
 src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java                                      |    3 
 src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java |    3 
 src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java                       |    4 
 src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java                                            |    6 
 src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java                                     |    6 
 src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java                        |  115 ++
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java             |    5 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java                             |    2 
 src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java                                          |   20 
 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java                                    |    9 
 src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java                                       |    4 
 src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java                               |    5 
 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java                     |   22 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java                           |  211 ++---
 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java                                        |   45 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java                |    3 
 src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java                                    |    8 
 src/main/java/com/genersoft/iot/vmp/utils/ConfigConst.java                                                |    8 
 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java                                    |   54 +
 pom.xml                                                                                                   |    7 
 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java                                   |    8 
 src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java                              |    3 
 src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java                                                 |  190 ----
 src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java                                     |   70 +
 src/main/java/com/genersoft/iot/vmp/service/IMediaService.java                                            |    5 
 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java                                              |   34 
 src/main/java/com/genersoft/iot/vmp/gb28181/session/SsrcConfig.java                                       |  140 +++
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java                |    3 
 src/main/resources/wvp.sqlite                                                                             |    0 
 src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java                                      |   30 
 src/main/resources/all-application.yml                                                                    |    7 
 src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java                                 |   24 
 src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java                                   |    1 
 /dev/null                                                                                                 |   92 --
 src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java                                                 |   28 
 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java                                    |   24 
 src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java                                   |   10 
 src/main/java/com/genersoft/iot/vmp/utils/SerializeUtils.java                                             |   31 
 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java                             |   25 
 src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java                              |    9 
 55 files changed, 1,318 insertions(+), 944 deletions(-)

diff --git a/pom.xml b/pom.xml
index 93b4257..077f8f1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -46,6 +46,7 @@
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 		<maven.build.timestamp.format>MMddHHmm</maven.build.timestamp.format>
 		<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>
@@ -80,6 +81,12 @@
 			<artifactId>spring-boot-starter-security</artifactId>
 		</dependency>
 
+		<dependency>
+			<groupId>redis.clients</groupId>
+			<artifactId>jedis</artifactId>
+			<version>${jedis-version}</version>
+		</dependency>
+
 		<!-- druid鏁版嵁搴撹繛鎺ユ睜 -->
 		<dependency>
 			<groupId>com.alibaba</groupId>
diff --git a/sql/mysql.sql b/sql/mysql.sql
index 0bb4c03..5d8bbfc 100644
--- a/sql/mysql.sql
+++ b/sql/mysql.sql
@@ -1,112 +1,145 @@
 -- 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
 (
-    deviceId           varchar(50) not null
+    deviceId      varchar(50)  not null
         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
 (
-    channelId   varchar(50) not null,
+    channelId   varchar(50)  not 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,
     registerWay int          null,
-    certNum     varchar(50) null,
+    certNum     varchar(50)  null,
     certifiable 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,
     password    varchar(255) null,
     PTZType     int          null,
     status      int          null,
     longitude   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)
 );
 
 create table device_mobile_position
 (
-    deviceId       varchar(50) not null,
+    deviceId       varchar(50)  not null,
     deviceName     varchar(255) null,
-    time           varchar(50) not null,
+    time           varchar(50)  not null,
     longitude      double       not null,
     latitude       double       not null,
     altitude       double       null,
     speed          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)
 );
 
 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)
+);
+
+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
 (
-    id          int auto_increment,
+    id             int auto_increment,
     enable         int          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,
-    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,
-    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,
     rtcp           int          null,
-    status         bit(1)   null,
+    status         bit          null,
     primary key (id, serverGBId)
 );
 
@@ -121,7 +154,7 @@
 
 create table platform_gb_stream
 (
-    platformId varchar(50) not null,
+    platformId varchar(50)  not null,
     app        varchar(255) not null,
     stream     varchar(255) not null,
     primary key (platformId, app, stream)
@@ -129,7 +162,7 @@
 
 create table stream_proxy
 (
-    type           varchar(50) not null,
+    type           varchar(50)  not null,
     app            varchar(255) not null,
     stream         varchar(255) not null,
     url            varchar(255) null,
@@ -137,11 +170,12 @@
     dst_url        varchar(255) null,
     timeout_ms     int          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)
 );
 
@@ -149,11 +183,12 @@
 (
     app              varchar(255) not null,
     stream           varchar(255) not null,
-    totalReaderCount varchar(50) null,
+    totalReaderCount varchar(50)  null,
     originType       int          null,
-    originTypeStr    varchar(50) null,
+    originTypeStr    varchar(50)  null,
     createStamp      int          null,
     aliveSecond      int          null,
+    mediaServerId    varchar(50)  null,
     primary key (app, stream)
 );
 
@@ -164,31 +199,6 @@
     username    varchar(255) not null,
     password    varchar(255) 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
-);
\ No newline at end of file
diff --git a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
index 5749314..cb2b173 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
@@ -12,6 +12,8 @@
 
 	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 DEVICE_PREFIX = "VMP_DEVICE_";
@@ -45,4 +47,8 @@
 	public static final String EVENT_OUTLINE_UNREGISTER = "1";
 	
 	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_";
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java
index f2a0bcd..744e56f 100644
--- a/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java
+++ b/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java
@@ -1,13 +1,16 @@
 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 org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.util.StringUtils;
 
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
 @Configuration("mediaConfig")
-public class MediaConfig implements IMediaServerItem {
+public class MediaConfig{
 
     @Value("${media.id:}")
     private String id;
@@ -20,6 +23,9 @@
 
     @Value("${sip.ip}")
     private String sipIp;
+
+    @Value("${sip.domain}")
+    private String sipDomain;
 
     @Value("${media.sdp-ip:${media.ip}}")
     private String sdpIp;
@@ -66,29 +72,12 @@
     @Value("${media.record-assist-port:0}")
     private Integer recordAssistPort = 0;
 
-    private String updateTime;
-
-    private String createTime;
-
-    private boolean docker = false;
-
-    private int count;
-
-
     public String getId() {
         return id;
     }
 
-    public void setId(String id) {
-        this.id = id;
-    }
-    
     public String getIp() {
         return ip;
-    }
-
-    public void setIp(String ip) {
-        this.ip = ip;
     }
 
     public String getHookIp() {
@@ -100,76 +89,24 @@
 
     }
 
-    public void setHookIp(String hookIp) {
-        this.hookIp = hookIp;
-    }
-
     public String getSipIp() {
         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() {
         return httpPort;
     }
 
-    @Override
-    public void setHttpPort(int httpPort) {
-
-    }
-
-    public void setHttpPort(Integer httpPort) {
-        this.httpPort = httpPort;
-    }
-
     public int getHttpSSlPort() {
         return httpSSlPort;
-    }
-
-    @Override
-    public void setHttpSSlPort(int httpSSlPort) {
-
-    }
-
-    public void setHttpSSlPort(Integer httpSSlPort) {
-        this.httpSSlPort = httpSSlPort;
     }
 
     public int getRtmpPort() {
         return rtmpPort;
     }
-
-    @Override
-    public void setRtmpPort(int rtmpPort) {
-
-    }
-
-    public void setRtmpPort(Integer rtmpPort) {
-        this.rtmpPort = rtmpPort;
-    }
-
+    
     public int getRtmpSSlPort() {
         return rtmpSSlPort;
-    }
-
-    @Override
-    public void setRtmpSSlPort(int rtmpSSlPort) {
-
-    }
-
-    public void setRtmpSSlPort(Integer rtmpSSlPort) {
-        this.rtmpSSlPort = rtmpSSlPort;
     }
 
     public int getRtpProxyPort() {
@@ -181,102 +118,36 @@
 
     }
 
-    @Override
-    public void setRtpProxyPort(int rtpProxyPort) {
-
-    }
-
-    public void setRtpProxyPort(Integer rtpProxyPort) {
-        this.rtpProxyPort = rtpProxyPort;
-    }
-
     public int getRtspPort() {
         return rtspPort;
-    }
-
-    @Override
-    public void setRtspPort(int rtspPort) {
-
-    }
-
-    public void setRtspPort(Integer rtspPort) {
-        this.rtspPort = rtspPort;
     }
 
     public int getRtspSSLPort() {
         return rtspSSLPort;
     }
 
-    @Override
-    public void setRtspSSLPort(int rtspSSLPort) {
-
-    }
-
-    public void setRtspSSLPort(Integer rtspSSLPort) {
-        this.rtspSSLPort = rtspSSLPort;
-    }
-
     public boolean isAutoConfig() {
         return autoConfig;
-    }
-
-    public void setAutoConfig(boolean autoConfig) {
-        this.autoConfig = autoConfig;
     }
 
     public String getSecret() {
         return secret;
     }
 
-    public void setSecret(String secret) {
-        this.secret = secret;
-    }
-
     public String getStreamNoneReaderDelayMS() {
         return streamNoneReaderDelayMS;
-    }
-
-    public void setStreamNoneReaderDelayMS(String streamNoneReaderDelayMS) {
-        this.streamNoneReaderDelayMS = streamNoneReaderDelayMS;
     }
 
     public boolean isRtpEnable() {
         return rtpEnable;
     }
 
-    public void setRtpEnable(boolean rtpEnable) {
-        this.rtpEnable = rtpEnable;
-    }
-
     public String getRtpPortRange() {
         return rtpPortRange;
     }
-
-    public void setRtpPortRange(String rtpPortRange) {
-        this.rtpPortRange = rtpPortRange;
-    }
-
+    
     public int getRecordAssistPort() {
         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() {
@@ -295,13 +166,11 @@
         }
     }
 
-
-
     public MediaServerItem getMediaSerItem(){
         MediaServerItem mediaServerItem = new MediaServerItem();
         mediaServerItem.setId(id);
         mediaServerItem.setIp(ip);
-        mediaServerItem.setDocker(true);
+        mediaServerItem.setDefaultServer(true);
         mediaServerItem.setHookIp(hookIp);
         mediaServerItem.setSdpIp(sdpIp);
         mediaServerItem.setStreamIp(streamIp);
@@ -318,39 +187,12 @@
         mediaServerItem.setRtpEnable(rtpEnable);
         mediaServerItem.setRtpPortRange(rtpPortRange);
         mediaServerItem.setRecordAssistPort(recordAssistPort);
-        mediaServerItem.setCreateTime(createTime);
-        mediaServerItem.setUpdateTime(updateTime);
-        mediaServerItem.setCount(count);
+
+        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())));
+
         return mediaServerItem;
     }
 
-    @Override
-    public String getUpdateTime() {
-        return updateTime;
-    }
-
-    @Override
-    public void setUpdateTime(String updateTime) {
-        this.updateTime = updateTime;
-    }
-
-    @Override
-    public String getCreateTime() {
-        return createTime;
-    }
-
-    @Override
-    public void setCreateTime(String createTime) {
-        this.createTime = createTime;
-    }
-
-    @Override
-    public int getCount() {
-        return count;
-    }
-
-    @Override
-    public void setCount(int count) {
-        this.count = count;
-    }
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java
index c2fb326..ab327b0 100644
--- a/src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java
+++ b/src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java
@@ -1,6 +1,6 @@
 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 org.apache.catalina.connector.ClientAbortException;
 import org.apache.http.HttpHost;
@@ -49,7 +49,7 @@
         @Override
         protected String rewriteQueryStringFromRequest(HttpServletRequest servletRequest, String queryString) {
             String queryStr = super.rewriteQueryStringFromRequest(servletRequest, queryString);
-            IMediaServerItem mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI());
+            MediaServerItem mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI());
             if (mediaInfo != null) {
                 if (!StringUtils.isEmpty(queryStr)) {
                     queryStr += "&secret=" + mediaInfo.getSecret();
@@ -88,7 +88,7 @@
         @Override
         protected String getTargetUri(HttpServletRequest servletRequest) {
             String requestURI = servletRequest.getRequestURI();
-            IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
+            MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
 
             String uri = null;
             if (mediaInfo != null) {
@@ -106,7 +106,7 @@
         @Override
         protected HttpHost getTargetHost(HttpServletRequest servletRequest) {
             String requestURI = servletRequest.getRequestURI();
-            IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
+            MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
             HttpHost host;
             if (mediaInfo != null) {
                 host = new HttpHost(mediaInfo.getIp(), mediaInfo.getHttpPort());
@@ -120,7 +120,7 @@
         /**
          * 鏍规嵁uri鑾峰彇娴佸獟浣撲俊鎭�
          */
-        IMediaServerItem getMediaInfoByUri(String uri){
+        MediaServerItem getMediaInfoByUri(String uri){
             String[] split = uri.split("/");
             String mediaServerId = split[2];
             return mediaServerService.getOne(mediaServerId);
@@ -132,7 +132,7 @@
         @Override
         protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) {
             String requestURI = servletRequest.getRequestURI();
-            IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
+            MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
             String url = super.rewriteUrlFromRequest(servletRequest);
             if (mediaInfo == null) {
                 return  url;
@@ -186,7 +186,7 @@
         @Override
         protected String getTargetUri(HttpServletRequest servletRequest) {
             String requestURI = servletRequest.getRequestURI();
-            IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
+            MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
 
             String uri = null;
             if (mediaInfo != null) {
@@ -204,7 +204,7 @@
         @Override
         protected HttpHost getTargetHost(HttpServletRequest servletRequest) {
             String requestURI = servletRequest.getRequestURI();
-            IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
+            MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
             HttpHost host;
             if (mediaInfo != null) {
                 host = new HttpHost(mediaInfo.getIp(), mediaInfo.getRecordAssistPort());
@@ -218,7 +218,7 @@
         /**
          * 鏍规嵁uri鑾峰彇娴佸獟浣撲俊鎭�
          */
-        IMediaServerItem getMediaInfoByUri(String uri){
+        MediaServerItem getMediaInfoByUri(String uri){
             String[] split = uri.split("/");
             String mediaServerId = split[2];
             return mediaServerService.getOne(mediaServerId);
@@ -230,7 +230,7 @@
         @Override
         protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) {
             String requestURI = servletRequest.getRequestURI();
-            IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
+            MediaServerItem mediaInfo = getMediaInfoByUri(requestURI);
             String url = super.rewriteUrlFromRequest(servletRequest);
             if (mediaInfo == null) {
                 return  url;
diff --git a/src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java
index 0b3e23b..ee90788 100644
--- a/src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java
+++ b/src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java
@@ -1,5 +1,7 @@
 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.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -10,6 +12,8 @@
 
 import com.alibaba.fastjson.parser.ParserConfig;
 import com.genersoft.iot.vmp.utils.redis.FastJsonRedisSerializer;
+import redis.clients.jedis.JedisPool;
+import redis.clients.jedis.JedisPoolConfig;
 
 /**
  * @Description:Redis涓棿浠堕厤缃被锛屼娇鐢╯pring-data-redis闆嗘垚锛岃嚜鍔ㄤ粠application.yml涓姞杞絩edis閰嶇疆
@@ -19,6 +23,37 @@
  */
 @Configuration
 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")
 	public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
@@ -34,7 +69,7 @@
 		template.setHashKeySerializer(new StringRedisSerializer());
 		template.setConnectionFactory(redisConnectionFactory);
 		// 浣跨敤fastjson鏃堕渶璁剧疆姝ら」锛屽惁鍒欎細鎶ュ紓甯竛ot support type
-		ParserConfig.getGlobalInstance().setAutoTypeSupport(true); 
+		ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
 		return template;
 	}
 
diff --git a/src/main/java/com/genersoft/iot/vmp/conf/SipDeviceRunner.java b/src/main/java/com/genersoft/iot/vmp/conf/SipDeviceRunner.java
deleted file mode 100644
index 2b7ab1a..0000000
--- a/src/main/java/com/genersoft/iot/vmp/conf/SipDeviceRunner.java
+++ /dev/null
@@ -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();
-    }
-}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
index 0a76f69..e71ac05 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
@@ -12,6 +12,7 @@
 import javax.sip.message.Response;
 
 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
+import gov.nist.javax.sip.SipProviderImpl;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -39,7 +40,7 @@
 	@Autowired
 	private SipSubscribe sipSubscribe;
 
-	private SipStack sipStack;
+	private SipStackImpl sipStack;
 
 	private SipFactory sipFactory;
 
@@ -52,7 +53,7 @@
 	private ThreadPoolExecutor initSipServer() {
 		
 		int processThreadNum = Runtime.getRuntime().availableProcessors() * 10;
-		LinkedBlockingQueue<Runnable> processQueue = new LinkedBlockingQueue<Runnable>(10000);
+		LinkedBlockingQueue<Runnable> processQueue = new LinkedBlockingQueue<>(10000);
 		processThreadPool = new ThreadPoolExecutor(processThreadNum,processThreadNum,
 				0L,TimeUnit.MILLISECONDS,processQueue,
 				new ThreadPoolExecutor.CallerRunsPolicy());
@@ -88,17 +89,14 @@
 
 	@Bean("tcpSipProvider")
 	@DependsOn("sipStack")
-	private SipProvider startTcpListener() {
+	private SipProviderImpl startTcpListener() {
 		ListeningPoint tcpListeningPoint = null;
-		SipProvider tcpSipProvider  = null;
+		SipProviderImpl tcpSipProvider  = null;
 		try {
 			tcpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getSipPort(), "TCP");
-			tcpSipProvider = sipStack.createSipProvider(tcpListeningPoint);
+			tcpSipProvider = (SipProviderImpl)sipStack.createSipProvider(tcpListeningPoint);
 			tcpSipProvider.addSipListener(this);
 			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) {
 			e.printStackTrace();
 		} catch (InvalidArgumentException e) {
@@ -114,13 +112,14 @@
 	
 	@Bean("udpSipProvider")
 	@DependsOn("sipStack")
-	private SipProvider startUdpListener() {
+	private SipProviderImpl startUdpListener() {
 		ListeningPoint udpListeningPoint = null;
-		SipProvider udpSipProvider = null;
+		SipProviderImpl udpSipProvider = null;
 		try {
 			udpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getSipPort(), "UDP");
-			udpSipProvider = sipStack.createSipProvider(udpListeningPoint);
+			udpSipProvider = (SipProviderImpl)sipStack.createSipProvider(udpListeningPoint);
 			udpSipProvider.addSipListener(this);
+//			udpSipProvider.setAutomaticDialogSupportEnabled(false);
 		} catch (TransportNotSupportedException e) {
 			e.printStackTrace();
 		} catch (InvalidArgumentException e) {
@@ -141,7 +140,7 @@
 	 */
 	@Override
 	public void processRequest(RequestEvent evt) {
-//		logger.debug(evt.getRequest().toString());
+		logger.debug(evt.getRequest().toString());
 		// 鐢变簬jainsip鏄崟绾跨▼绋嬪簭锛屼负鎻愰珮鎬ц兘骞跺彂澶勭悊
 		processThreadPool.execute(() -> {
 			if (processorFactory != null) {
@@ -153,7 +152,7 @@
 	@Override
 	public void processResponse(ResponseEvent evt) {
 		Response response = evt.getResponse();
-//		logger.debug(evt.getResponse().toString());
+		logger.debug(evt.getResponse().toString());
 		int status = response.getStatusCode();
 		if (((status >= 200) && (status < 300)) || status == 401) { // Success!
 			ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt);
@@ -163,6 +162,7 @@
 				// TODO Auto-generated catch block
 				e.printStackTrace();
 			}
+
 			if (evt.getResponse() != null && sipSubscribe.getOkSubscribesSize() > 0 ) {
 				CallIdHeader callIdHeader = (CallIdHeader)evt.getResponse().getHeader(CallIdHeader.NAME);
 				if (callIdHeader != null) {
@@ -220,7 +220,6 @@
 	@Override
 	public void processIOException(IOExceptionEvent exceptionEvent) {
 		// TODO Auto-generated method stub
-
 	}
 
 	/**
@@ -236,7 +235,6 @@
 	@Override
 	public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
 		// TODO Auto-generated method stub
-
 	}
 
 	/**
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java
new file mode 100644
index 0000000..47d4d8a
--- /dev/null
+++ b/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;
+    }
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java
index aed2100..0b4bc88 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java
@@ -6,7 +6,6 @@
 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
 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.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@@ -77,7 +76,7 @@
                 }
                 stream.append(sendRtpItem.getStreamId());
                 redisCatchStorage.deleteSendRTPServer(event.getPlatformGbID(), sendRtpItem.getChannelId());
-                IMediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
+                MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
                 Map<String, Object> param = new HashMap<>();
                 param.put("vhost", "__defaultVhost__");
                 param.put("app", app.toString());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/session/SsrcConfig.java b/src/main/java/com/genersoft/iot/vmp/gb28181/session/SsrcConfig.java
new file mode 100644
index 0000000..e96e6a5
--- /dev/null
+++ b/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);
+            }
+        }
+    }
+
+
+    /**
+     * 鑾峰彇瑙嗛棰勮鐨凷SRC鍊�,绗竴浣嶅浐瀹氫负0
+     * @return ssrc
+     */
+    public String getPlaySsrc() {
+        return "0" + getSsrcPrefix() + getSN();
+    }
+
+    /**
+     * 鑾峰彇褰曞儚鍥炴斁鐨凷SRC鍊�,绗竴浣嶅浐瀹氫负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;
+    }
+
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/session/SsrcUtil.java b/src/main/java/com/genersoft/iot/vmp/gb28181/session/SsrcUtil.java
deleted file mode 100644
index 7377997..0000000
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/session/SsrcUtil.java
+++ /dev/null
@@ -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宸ュ叿绫汇�係SRC鍊肩敱10浣嶅崄杩涘埗鏁存暟缁勬垚鐨勫瓧绗︿覆锛岀涓�浣嶄负0浠h〃瀹炲喌锛屼负1鍒欎唬琛ㄥ洖鏀撅紱绗簩浣嶈嚦绗叚浣嶇敱鐩戞帶鍩烮D鐨勭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));
-			}
-		}
-	}
-
-	/**
-	 * 鑾峰彇瑙嗛棰勮鐨凷SRC鍊�,绗竴浣嶅浐瀹氫负0
-	 * 
-	 */
-	public static String getPlaySsrc() {
-		return "0" + getSsrcPrefix() + getSN();
-	}
-
-	/**
-	 * 鑾峰彇褰曞儚鍥炴斁鐨凷SRC鍊�,绗竴浣嶅浐瀹氫负1
-	 * 
-	 */
-	public static String getPlayBackSsrc() {
-		return "1" + getSsrcPrefix() + getSN();
-	}
-
-	/**
-	 * 閲婃斁ssrc锛屼富瑕佺敤瀹岀殑ssrc涓�瀹氳閲婃斁锛屽惁鍒欎細鑰楀敖
-	 * 
-	 */
-	public static void releaseSsrc(String ssrc) {
-		if (ssrc == null) {
-			logger.error("瑕侀噴鏀緎src涓簄ull");
-			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;
-	}
-}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java b/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java
index 9e402e1..f9d3a69 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java
@@ -1,9 +1,23 @@
 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 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;
 
 /**    
@@ -14,50 +28,85 @@
 @Component
 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 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 String createPlayBackSsrc(){
-		return SsrcUtil.getPlayBackSsrc();
+
+	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 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 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 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 SsrcTransaction getSsrcTransaction(String deviceId, String channelId){
+		SsrcTransaction ssrcTransaction = (SsrcTransaction)redisUtil.get(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + deviceId + "_" + channelId);
+		return ssrcTransaction;
 	}
 
 	public String getStreamId(String deviceId, String channelId){
-		return streamIdMap.get(deviceId + "_" + 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 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) {
-		sessionMap.remove(deviceId + "_" + channelId);
-		if (ssrcMap.get(deviceId + "_" + channelId) != null) {
-			SsrcUtil.releaseSsrc(ssrcMap.get(deviceId + "_" + channelId));
+		SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
+		if (ssrcTransaction == null) return;
+		redisUtil.del(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX +  deviceId + "_" + channelId);
+	}
+
+	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);
 		}
-		ssrcMap.remove(deviceId + "_" + channelId);
-		streamIdMap.remove(deviceId + "_" + channelId);
-	}
-
-	public ConcurrentHashMap<String, ClientTransaction> getSessionMap() {
-		return sessionMap;
-	}
-
-	public ConcurrentHashMap<String, String> getSsrcMap() {
-		return ssrcMap;
-	}
-
-	public ConcurrentHashMap<String, String> getStreamIdMap() {
-		return streamIdMap;
+		return result;
 	}
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java
index e2ff0f4..30c9e95 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java
@@ -7,6 +7,7 @@
 import javax.sip.message.Request;
 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.media.zlm.ZLMRTPServerFactory;
 import com.genersoft.iot.vmp.service.IMediaServerService;
@@ -107,7 +108,6 @@
 
 	@Autowired
 	private IMediaServerService mediaServerService;
-
 
 	// 娉細杩欓噷浣跨敤娉ㄨВ浼氬鑷村惊鐜緷璧栨敞鍏ワ紝鏆傜敤springBean
 	private SipProvider tcpSipProvider;
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
index 99da23d..10611dc 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
@@ -3,8 +3,8 @@
 import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
 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.service.bean.SSRCInfo;
 
 /**    
  * @Description:璁惧鑳藉姏鎺ュ彛锛岀敤浜庡畾涔夎澶囩殑鎺у埗銆佹煡璇㈣兘鍔�   
@@ -92,7 +92,7 @@
 	 * @param device  瑙嗛璁惧
 	 * @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 @@
 	 * @param startTime 寮�濮嬫椂闂�,鏍煎紡瑕佹眰锛歽yyy-MM-dd HH:mm:ss
 	 * @param endTime 缁撴潫鏃堕棿,鏍煎紡瑕佹眰锛歽yyy-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 @@
 	 * @param endTime 缁撴潫鏃堕棿,鏍煎紡瑕佹眰锛歽yyy-MM-dd HH:mm:ss
 	 * @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);
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
index d2318dc..f1223d5 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
+++ b/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;
 
+import java.lang.reflect.Field;
 import java.text.ParseException;
+import java.util.HashSet;
 
 import javax.sip.*;
 import javax.sip.address.SipURI;
@@ -8,18 +10,21 @@
 import javax.sip.header.ViaHeader;
 import javax.sip.message.Request;
 
-import com.alibaba.fastjson.JSONArray;
 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.gb28181.bean.SsrcTransaction;
 import com.genersoft.iot.vmp.media.zlm.*;
 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.service.IMediaServerService;
+import com.genersoft.iot.vmp.service.bean.SSRCInfo;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 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.stack.SIPDialog;
+import gov.nist.javax.sip.stack.SIPTransaction;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -35,7 +40,6 @@
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
 import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
 import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
-import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
 import org.springframework.util.StringUtils;
 
 /**    
@@ -55,12 +59,12 @@
 	@Lazy
 	@Autowired
 	@Qualifier(value="tcpSipProvider")
-	private SipProvider tcpSipProvider;
+	private SipProviderImpl tcpSipProvider;
 
 	@Lazy
 	@Autowired
 	@Qualifier(value="udpSipProvider")
-	private SipProvider udpSipProvider;
+	private SipProviderImpl udpSipProvider;
 
 	@Autowired
 	private SIPRequestHeaderProvider headerProvider;
@@ -75,9 +79,6 @@
 	private IRedisCatchStorage redisCatchStorage;
 
 	@Autowired
-	private ZLMRTPServerFactory zlmrtpServerFactory;
-
-	@Autowired
 	private UserSetup userSetup;
 
 	@Autowired
@@ -85,6 +86,11 @@
 
 	@Autowired
 	private SipSubscribe sipSubscribe;
+
+	@Autowired
+	private IMediaServerService mediaServerService;
+
+	private SIPDialog dialog;
 
 	public SipConfig getSipConfig() {
 		return sipConfig;
@@ -334,26 +340,13 @@
 	  * @param errorEvent sip閿欒璁㈤槄
 	  */
 	@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 {
 			if (device == null) return;
 			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;
-			// 浣跨敤鍔ㄦ�乽dp绔彛
-			if (mediaServerItem.isRtpEnable()) {
-				mediaPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId);
-			}else {
-				mediaPort = mediaServerItem.getRtpProxyPort();
-			}
-			logger.info("{} 鍒嗛厤鐨刏LM涓�: {} [{}:{}]", streamId, mediaServerItem.getId(), mediaServerItem.getIp(), mediaPort);
+			logger.info("{} 鍒嗛厤鐨刏LM涓�: {} [{}:{}]", streamId, mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
 			// 娣诲姞璁㈤槄
 			JSONObject subscribeKey = new JSONObject();
 			subscribeKey.put("app", "rtp");
@@ -361,7 +354,7 @@
 			subscribeKey.put("regist", true);
 			subscribeKey.put("mediaServerId", mediaServerItem.getId());
 			subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
-					(IMediaServerItem mediaServerItemInUse, JSONObject json)->{
+					(MediaServerItem mediaServerItemInUse, JSONObject json)->{
 				if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
 				event.response(mediaServerItemInUse, json);
 				subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
@@ -369,7 +362,6 @@
 			//
 			StringBuffer content = new StringBuffer(200);
 			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("s=Play\r\n");
 			content.append("c=IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");
@@ -377,11 +369,11 @@
 
 			if (userSetup.isSeniorSdp()) {
 				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)) {
-					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)) {
-					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=rtpmap:96 PS/90000\r\n");
@@ -402,11 +394,11 @@
 				}
 			}else {
 				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)) {
-					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)) {
-					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=rtpmap:96 PS/90000\r\n");
@@ -421,20 +413,25 @@
 				}
 			}
 
-			content.append("y="+ssrc+"\r\n");//ssrc
+			content.append("y="+ssrcInfo.getSsrc()+"\r\n");//ssrc
 
 			String tm = Long.toString(System.currentTimeMillis());
 
 			CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.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);
+				mediaServerService.releaseSsrc(mediaServerItem, ssrcInfo.getSsrc());
 				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) {
 			e.printStackTrace();
@@ -450,30 +447,21 @@
 	 * @param endTime 缁撴潫鏃堕棿,鏍煎紡瑕佹眰锛歽yyy-MM-dd HH:mm:ss
 	 */ 
 	@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) {
 		try {
-			String ssrc = streamSession.createPlayBackSsrc();
-			String streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
 
-			Integer mediaPort = null;
-			// 浣跨敤鍔ㄦ�乽dp绔彛
-			if (mediaServerItem.isRtpEnable()) {
-				mediaPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId);
-			}else {
-				mediaPort = mediaServerItem.getRtpProxyPort();
-			}
-			logger.info("{} 鍒嗛厤鐨刏LM涓�: {} [{}:{}]", streamId, mediaServerItem.getId(), mediaServerItem.getIp(), mediaPort);
+			logger.info("{} 鍒嗛厤鐨刏LM涓�: {} [{}:{}]", ssrcInfo.getStreamId(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
 
 			// 娣诲姞璁㈤槄
 			JSONObject subscribeKey = new JSONObject();
 			subscribeKey.put("app", "rtp");
-			subscribeKey.put("stream", streamId);
+			subscribeKey.put("stream", ssrcInfo.getStreamId());
 			subscribeKey.put("regist", true);
 			subscribeKey.put("mediaServerId", mediaServerItem.getId());
 			logger.debug("褰曞儚鍥炴斁娣诲姞璁㈤槄锛岃闃呭唴瀹癸細" + subscribeKey.toString());
 			subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
-					(IMediaServerItem mediaServerItemInUse, JSONObject json)->{
+					(MediaServerItem mediaServerItemInUse, JSONObject json)->{
 				if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
 				event.response(mediaServerItemInUse, json);
 				subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
@@ -494,11 +482,11 @@
 
 			if (userSetup.isSeniorSdp()) {
 				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)) {
-					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)) {
-					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=rtpmap:96 PS/90000\r\n");
@@ -519,11 +507,11 @@
 				}
 			}else {
 				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)) {
-					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)) {
-					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=rtpmap:96 PS/90000\r\n");
@@ -538,7 +526,7 @@
 				}
 			}
 
-	        content.append("y="+ssrc+"\r\n");//ssrc
+	        content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
 	        
 			String tm = Long.toString(System.currentTimeMillis());
 
@@ -547,9 +535,11 @@
 
 	        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) {
 			e.printStackTrace();
 		}
@@ -565,30 +555,20 @@
 	 * @param downloadSpeed 涓嬭浇鍊嶉�熷弬鏁�
 	 */ 
 	@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) {
 		try {
-			String ssrc = streamSession.createPlayBackSsrc();
-			String streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
-
-			Integer mediaPort = null;
-			// 浣跨敤鍔ㄦ�乽dp绔彛
-			if (mediaServerItem.isRtpEnable()) {
-				mediaPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId);
-			}else {
-				mediaPort = mediaServerItem.getRtpProxyPort();
-			}
-			logger.info("{} 鍒嗛厤鐨刏LM涓�: {} [{}:{}]", streamId, mediaServerItem.getId(), mediaServerItem.getIp(), mediaPort);
+			logger.info("{} 鍒嗛厤鐨刏LM涓�: {} [{}:{}]", ssrcInfo.getStreamId(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
 
 			// 娣诲姞璁㈤槄
 			JSONObject subscribeKey = new JSONObject();
 			subscribeKey.put("app", "rtp");
-			subscribeKey.put("stream", streamId);
+			subscribeKey.put("stream", ssrcInfo.getStreamId());
 			subscribeKey.put("regist", true);
 			subscribeKey.put("mediaServerId", mediaServerItem.getId());
 			logger.debug("褰曞儚鍥炴斁娣诲姞璁㈤槄锛岃闃呭唴瀹癸細" + subscribeKey.toString());
 			subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
-					(IMediaServerItem mediaServerItemInUse, JSONObject json)->{
+					(MediaServerItem mediaServerItemInUse, JSONObject json)->{
 				if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
 				event.response(mediaServerItemInUse, json);
 				subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
@@ -609,11 +589,11 @@
 
 			if (userSetup.isSeniorSdp()) {
 				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)) {
-					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)) {
-					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=rtpmap:96 PS/90000\r\n");
@@ -634,11 +614,11 @@
 				}
 			}else {
 				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)) {
-					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)) {
-					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=rtpmap:96 PS/90000\r\n");
@@ -654,7 +634,7 @@
 			}
 			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());
 
@@ -664,7 +644,7 @@
 	        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);
+	        streamSession.put(device.getDeviceId(), channelId, ssrcInfo.getSsrc(), ssrcInfo.getStreamId(), mediaServerItem.getId(), transaction);
 
 		} catch ( SipException | ParseException | InvalidArgumentException e) {
 			e.printStackTrace();
@@ -684,53 +664,35 @@
 	 */
 	@Override
 	public void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent) {
-		StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
 		try {
 			ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId);
-			// 鏈嶅姟閲嶅惎鍚�, 鏃犳硶鐩存帴鍙戦�乥ye锛� 閫氳繃鎵嬪姩鏋勫缓鍙戦��
-//			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) {
 				logger.warn("[ {} -> {}]鍋滄瑙嗛娴佺殑鏃跺�欏彂鐜颁簨鍔″凡涓㈠け", deviceId, channelId);
 				return;
 			}
-			Dialog dialog = transaction.getDialog();
+			SIPDialog dialog = streamSession.getDialog(deviceId, channelId);
 			if (dialog == null) {
 				logger.warn("[ {} -> {}]鍋滄瑙嗛娴佺殑鏃跺�欏彂鐜板璇濆凡涓㈠け", deviceId, channelId);
 				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);
 			SipURI byeURI = (SipURI) byeRequest.getRequestURI();
 			SIPRequest request = (SIPRequest)transaction.getRequest();
@@ -752,7 +714,12 @@
 
 			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) {
 			e.printStackTrace();
 		}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java
index 6f80971..7d9e5f7 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java
@@ -13,7 +13,6 @@
 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
 import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
 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.service.IMediaServerService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@@ -81,7 +80,7 @@
 			while (!rtpPushed) {
 				try {
 					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())) {
 							rtpPushed = true;
 							logger.info("宸茶幏鍙栬澶囨帹娴乕{}/{}]锛屽紑濮嬪悜涓婄骇鎺ㄦ祦[{}:{}]",
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java
index 50e8c32..ffa5377 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java
@@ -15,7 +15,6 @@
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
 import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
 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.service.IMediaServerService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@@ -65,7 +64,7 @@
 				param.put("stream",streamId);
 				param.put("ssrc",sendRtpItem.getSsrc());
 				logger.info("鍋滄鍚戜笂绾ф帹娴侊細" + streamId);
-				IMediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
+				MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
 				zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
 				redisCatchStorage.deleteSendRTPServer(platformGbId, channelId);
 				if (zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId) == 0) {
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java
index 7219dbb..1aa0079 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java
@@ -11,14 +11,11 @@
 import javax.sip.message.Request;
 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.transmit.cmd.impl.SIPCommander;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
 import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
 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.service.IMediaServerService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@@ -97,7 +94,7 @@
 				// 鏌ヨ骞冲彴涓嬫槸鍚︽湁璇ラ�氶亾
 				DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId);
 				GbStream gbStream = storager.queryStreamInParentPlatform(requesterId, channelId);
-				IMediaServerItem mediaServerItem = null;
+				MediaServerItem mediaServerItem = null;
 				// 涓嶆槸閫氶亾鍙兘鏄洿鎾祦
 				if (channel != null && gbStream == null ) {
 					if (channel.getStatus() == 0) {
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/InviteResponseProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/InviteResponseProcessor.java
index 7368c36..bcc7626 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/InviteResponseProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/response/impl/InviteResponseProcessor.java
@@ -3,14 +3,18 @@
 import java.text.ParseException;
 
 import javax.sip.*;
+import javax.sip.address.Address;
 import javax.sip.address.SipURI;
 import javax.sip.header.CSeqHeader;
 import javax.sip.message.Request;
 import javax.sip.message.Response;
 
+import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
 import gov.nist.javax.sip.ResponseEventExt;
+import gov.nist.javax.sip.stack.SIPDialog;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
 import com.genersoft.iot.vmp.conf.SipConfig;
@@ -27,6 +31,9 @@
 public class InviteResponseProcessor implements ISIPResponseProcessor {
 
 	 private final static Logger logger = LoggerFactory.getLogger(InviteResponseProcessor.class);
+
+	@Autowired
+	private VideoStreamSessionManager streamSession;
 
 	/**
 	 * 澶勭悊invite鍝嶅簲
@@ -46,7 +53,7 @@
 			// 涓嬪彂ack
 			if (statusCode == Response.OK) {
 				ResponseEventExt event = (ResponseEventExt)evt;
-				Dialog dialog = evt.getDialog();
+				SIPDialog dialog = (SIPDialog)evt.getDialog();
 				CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
 				Request reqAck = dialog.createAck(cseq.getSeqNumber());
 				SipURI requestURI = (SipURI) reqAck.getRequestURI();
@@ -54,7 +61,12 @@
 				requestURI.setPort(event.getRemotePort());
 				reqAck.setRequestURI(requestURI);
 				logger.info("鍚� " + event.getRemoteIpAddress() + ":" + event.getRemotePort() + "鍥炲ack");
+				SipURI sipURI = (SipURI)dialog.getRemoteParty().getURI();
+				String deviceId = requestURI.getUser();
+				String channelId = sipURI.getUser();
+
 				dialog.sendAck(reqAck);
+
 			}
 		} catch (InvalidArgumentException | SipException e) {
 			e.printStackTrace();
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
index b7aebf4..478772a 100644
--- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -3,15 +3,14 @@
 import java.util.List;
 import java.util.UUID;
 
-import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 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.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.service.IMediaServerService;
+import com.genersoft.iot.vmp.service.bean.SSRCInfo;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
 import com.genersoft.iot.vmp.service.IPlayService;
@@ -41,7 +40,6 @@
 public class ZLMHttpHookListener {
 
 	private final static Logger logger = LoggerFactory.getLogger(ZLMHttpHookListener.class);
-
 
 	@Autowired
 	private SIPCommander cmder;
@@ -125,7 +123,7 @@
 		String mediaServerId = json.getString("mediaServerId");
 		ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_play, json);
 		if (subscribe != null ) {
-			IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
+			MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
 			if (mediaInfo != null) {
 				subscribe.response(mediaInfo, json);
 			}
@@ -150,7 +148,7 @@
 		String mediaServerId = json.getString("mediaServerId");
 		ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_publish, json);
 		if (subscribe != null) {
-			IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
+			MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
 			if (mediaInfo != null) {
 				subscribe.response(mediaInfo, json);
 			}
@@ -237,7 +235,7 @@
 		String mediaServerId = json.getString("mediaServerId");
 		ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_shell_login, json);
 		if (subscribe != null ) {
-			IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
+			MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
 			if (mediaInfo != null) {
 				subscribe.response(mediaInfo, json);
 			}
@@ -264,7 +262,7 @@
 		String mediaServerId = json.getString("mediaServerId");
 		ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, json);
 		if (subscribe != null ) {
-			IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
+			MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
 			if (mediaInfo != null) {
 				subscribe.response(mediaInfo, json);
 			}
@@ -297,7 +295,7 @@
 				}
 			}else {
 				if (!"rtp".equals(app) ){
-					IMediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
+					MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
 					if (regist) {
 						zlmMediaListManager.addMedia(mediaServerItem, app, streamId);
 					}else {
@@ -369,7 +367,7 @@
 			logger.debug("ZLM HOOK on_stream_not_found API璋冪敤锛屽弬鏁帮細" + json.toString());
 		}
 		String mediaServerId = json.getString("mediaServerId");
-		IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
+		MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
 		if (userSetup.isAutoApplyPlay() && mediaInfo != null) {
 			String app = json.getString("app");
 			String streamId = json.getString("stream");
@@ -381,7 +379,13 @@
 					Device device = storager.queryVideoDevice(deviceId);
 					if (device != null) {
 						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());
 							playService.onPublishHandlerForPlay(mediaServerItemInuse, response, deviceId, channelId, uuid.toString());
 						}, null);
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java
index 62b18f5..be69df1 100644
--- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java
@@ -1,7 +1,6 @@
 package com.genersoft.iot.vmp.media.zlm;
 
 import com.alibaba.fastjson.JSONObject;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import org.springframework.stereotype.Component;
 
@@ -32,7 +31,7 @@
     }
 
     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<>();
@@ -58,6 +57,9 @@
                 if (result == null) {
                     result = key.getString(s).equals(hookResponse.getString(s));
                 }else {
+                    if (key.getString(s) == null) {
+                        continue;
+                    }
                     result = result && key.getString(s).equals(hookResponse.getString(s));
                 }
 
@@ -83,9 +85,9 @@
                 if (result == null) {
                     result = key.getString(s).equals(hookResponse.getString(s));
                 }else {
+                    if (key.getString(s) == null) continue;
                     result = result && key.getString(s).equals(hookResponse.getString(s));
                 }
-
             }
             if (null != result && result){
                 iterator.remove();
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java
index 3876309..7fc0a08 100644
--- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java
@@ -1,12 +1,9 @@
 package com.genersoft.iot.vmp.media.zlm;
 
-import com.alibaba.fastjson.JSONArray;
 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.StreamProxyItem;
 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.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
@@ -76,7 +73,7 @@
                     jsonObject.put("stream", streamPushItem.getStream());
                     jsonObject.put("mediaServerId", mediaServerItem.getId());
                     subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_play,jsonObject,
-                            (IMediaServerItem mediaServerItemInuse, JSONObject response)->{
+                            (MediaServerItem mediaServerItemInuse, JSONObject response)->{
                                 updateMedia(mediaServerItem, response.getString("app"), response.getString("stream"));
                             }
                     );
@@ -86,13 +83,13 @@
 
     }
 
-    public void addMedia(IMediaServerItem mediaServerItem, String app, String streamId) {
+    public void addMedia(MediaServerItem mediaServerItem, String app, String 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->{
 
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java
index 8e12e57..af8793a 100644
--- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java
@@ -2,14 +2,11 @@
 
 import com.alibaba.fastjson.JSON;
 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 okhttp3.*;
 import org.jetbrains.annotations.NotNull;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
 import java.io.*;
@@ -27,7 +24,7 @@
         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();
         String url = String.format("http://%s:%s/index/api/%s",  mediaServerItem.getIp(), mediaServerItem.getHttpPort(), api);
         JSONObject responseJSON = null;
@@ -93,7 +90,7 @@
     }
 
 
-    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();
         String url = String.format("http://%s:%s/index/api/%s",  mediaServerItem.getIp(), mediaServerItem.getHttpPort(), api);
         JSONObject responseJSON = null;
@@ -139,7 +136,7 @@
     }
 
 
-    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<>();
         if (app != null) param.put("app",app);
         if (stream != null) param.put("stream",stream);
@@ -148,15 +145,15 @@
         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);
     }
 
-    public JSONObject getMediaList(IMediaServerItem mediaServerItem,RequestCallback callback){
+    public JSONObject getMediaList(MediaServerItem mediaServerItem, RequestCallback 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<>();
         param.put("app",app);
         param.put("schema",schema);
@@ -165,13 +162,13 @@
         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<>();
         param.put("stream_id",stream_id);
         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){
         logger.info(src_url);
         logger.info(dst_url);
@@ -185,41 +182,41 @@
         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<>();
         param.put("key", key);
         return sendPost(mediaServerItem, "delFFmpegSource",param, null);
     }
 
-    public JSONObject getMediaServerConfig(IMediaServerItem mediaServerItem){
+    public JSONObject getMediaServerConfig(MediaServerItem mediaServerItem){
         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);
     }
 
-    public JSONObject openRtpServer(IMediaServerItem mediaServerItem,Map<String, Object> param){
+    public JSONObject openRtpServer(MediaServerItem mediaServerItem, Map<String, Object> param){
         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);
     }
 
-    public JSONObject listRtpServer(IMediaServerItem mediaServerItem) {
+    public JSONObject listRtpServer(MediaServerItem mediaServerItem) {
         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);
     }
 
-    public JSONObject stopSendRtp(IMediaServerItem mediaServerItem,Map<String, Object> param) {
+    public JSONObject stopSendRtp(MediaServerItem mediaServerItem, Map<String, Object> param) {
         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<>();
         param.put("vhost", "__defaultVhost__");
         param.put("app", app);
@@ -231,7 +228,7 @@
         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<>();
         param.put("vhost", "__defaultVhost__");
         param.put("app", app);
@@ -240,17 +237,17 @@
         return sendPost(mediaServerItem, "close_streams",param, null);
     }
 
-    public JSONObject getAllSession(IMediaServerItem mediaServerItem) {
+    public JSONObject getAllSession(MediaServerItem mediaServerItem) {
         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<>();
         param.put("local_port", localPortSStr);
         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<>();
         param.put("url", flvUrl);
         param.put("timeout_sec", timeout_sec);
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
index 5919c9f..0ddd904 100644
--- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
@@ -2,10 +2,7 @@
 
 import com.alibaba.fastjson.JSONArray;
 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.session.SsrcUtil;
-import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -21,28 +18,19 @@
     private Logger logger = LoggerFactory.getLogger("ZLMRTPServerFactory");
 
     @Autowired
-    private MediaConfig mediaConfig;
-
-    @Autowired
     private ZLMRESTfulUtils zlmresTfulUtils;
 
     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 @@
 
         Map<String, Object> param = new HashMap<>();
         int result = -1;
-        int newPort = getPortFromportRange();
+        int newPort = getPortFromportRange(mediaServerItem);
         param.put("port", newPort);
         param.put("enable_tcp", 1);
         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:
                     result= newPort;
                     break;
-                case -300: // id宸茬粡瀛樺湪, 鍙兘宸茬粡鍦ㄥ叾浠栫鍙f帹娴�
+                case -300: // id宸茬粡瀛樺湪, 鍙兘宸茬粡鍦ㄥ叾浠栫鍙f帹娴�, TODO 涔熷彲鑳芥槸璁惧涓嶇瓑ack灏辩洿鎺ユ帹娴佷簡, 闇�瑕佹煡璇笌璁剧疆鐨勬帹娴乮p绔彛鏄惁涓�鑷�
                     Map<String, Object> closeRtpServerParam = new HashMap<>();
                     closeRtpServerParam.put("stream_id", streamId);
                     zlmresTfulUtils.closeRtpServer(mediaServerItem, closeRtpServerParam);
@@ -77,7 +65,7 @@
                     result= createRTPServer(mediaServerItem, streamId);
                     break;
                 default:
-                    logger.error("鍒涘缓RTP Server 澶辫触 {}: " + jsonObject.getString("msg"), newPort);
+                    logger.error("鍒涘缓RTP Server 澶辫触 {}: " + openRtpServerResultJson.getString("msg"), newPort);
                     break;
             }
         }else {
@@ -87,7 +75,7 @@
         return result;
     }
 
-    public boolean closeRTPServer(IMediaServerItem serverItem, String streamId) {
+    public boolean closeRTPServer(MediaServerItem serverItem, String streamId) {
         boolean result = false;
         if (serverItem !=null){
             Map<String, Object> param = new HashMap<>();
@@ -107,21 +95,25 @@
         return result;
     }
 
-    private int getPortFromportRange() {
+    private int getPortFromportRange(MediaServerItem mediaServerItem) {
+        int currentPort = mediaServerItem.getCurrentPort();
         if (currentPort == 0) {
-            String[] portRangeStrArray = mediaConfig.getRtpPortRange().split(",");
+            String[] portRangeStrArray = mediaServerItem.getRtpPortRange().split(",");
             portRangeArray[0] = Integer.parseInt(portRangeStrArray[0]);
             portRangeArray[1] = Integer.parseInt(portRangeStrArray[1]);
         }
 
         if (currentPort == 0 || currentPort++ > portRangeArray[1]) {
             currentPort = portRangeArray[0];
+            mediaServerItem.setCurrentPort(currentPort);
             return portRangeArray[0];
         } else {
             if (currentPort % 2 == 1) {
                 currentPort++;
             }
-            return currentPort++;
+            currentPort++;
+            mediaServerItem.setCurrentPort(currentPort);
+            return currentPort;
         }
     }
 
@@ -135,10 +127,14 @@
      * @param tcp 鏄惁涓簍cp
      * @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) {
+            // TODO 楂樺苟鍙戞椂鍙兘鍥犱负鏈斁鍏ョ紦瀛樿�宻src鍐茬獊
+            serverItem.getSsrcConfig().releaseSsrc(playSsrc);
             closeRTPServer(serverItem, playSsrc);
         }else {
             logger.error("娌℃湁鍙敤鐨勭鍙�");
@@ -168,10 +164,12 @@
      * @param tcp 鏄惁涓簍cp
      * @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) {
+            // TODO 楂樺苟鍙戞椂鍙兘鍥犱负鏈斁鍏ョ紦瀛樿�宻src鍐茬獊
+            serverItem.getSsrcConfig().releaseSsrc(ssrc);
             closeRTPServer(serverItem, playSsrc);
         }else {
             logger.error("娌℃湁鍙敤鐨勭鍙�");
@@ -194,7 +192,7 @@
     /**
      * 璋冪敤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;
         JSONObject jsonObject = zlmresTfulUtils.startSendRtp(mediaServerItem, param);
         if (jsonObject == null) {
@@ -219,7 +217,7 @@
     /**
      * 鏌ヨ寰呰浆鎺ㄧ殑娴佹槸鍚﹀氨缁�
      */
-    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);
         return (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online"));
     }
@@ -229,7 +227,7 @@
      * @param streamId
      * @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);
         return mediaInfo.getInteger("totalReaderCount");
     }
@@ -237,7 +235,7 @@
     /**
      * 璋冪敤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;
         JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(mediaServerItem, param);
         if (jsonObject == null) {
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java
index d06c6c3..67b605c 100644
--- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java
@@ -4,22 +4,16 @@
 import com.alibaba.fastjson.JSONArray;
 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.StreamProxyItem;
 import com.genersoft.iot.vmp.service.IMediaServerService;
-import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
 import com.genersoft.iot.vmp.service.IStreamProxyService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
 import org.springframework.boot.CommandLineRunner;
 import org.springframework.core.annotation.Order;
 import org.springframework.stereotype.Component;
-import org.springframework.util.StringUtils;
 
-import javax.print.attribute.standard.Media;
 import java.util.*;
 
 @Component
@@ -47,16 +41,26 @@
 
     @Override
     public void run(String... strings) throws Exception {
-        IMediaServerItem presetMediaServer = mediaServerService.getOneByHostAndPort(
+        // 娓呮redis缂撳瓨鐨勫湪绾縵lm淇℃伅
+        mediaServerService.clearMediaServerForOnline();
+
+        // 灏嗛厤缃枃浠剁殑meida閰嶇疆鍐欏叆鏁版嵁搴�
+        MediaServerItem presetMediaServer = mediaServerService.getOneByHostAndPort(
                 mediaConfig.getIp(), mediaConfig.getHttpPort());
         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涔熶細浠庤繖閲岃繘鍏ョ郴缁�
         hookSubscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_server_started,null,
-                (IMediaServerItem mediaServerItem, JSONObject response)->{
+                (MediaServerItem mediaServerItem, JSONObject response)->{
             ZLMServerConfig zlmServerConfig = JSONObject.toJavaObject(response, ZLMServerConfig.class);
             if (zlmServerConfig !=null ) {
                 startGetMedia.remove(zlmServerConfig.getGeneralMediaServerId());
@@ -69,23 +73,25 @@
         logger.info("绛夊緟榛樿zlm鎺ュ叆...");
 
         // 鑾峰彇鎵�鏈夌殑zlm锛� 骞跺紑鍚富鍔ㄨ繛鎺�
-        List<IMediaServerItem> all = mediaServerService.getAll();
+        List<MediaServerItem> all = mediaServerService.getAll();
         if (presetMediaServer == null) {
             all.add(mediaConfig.getMediaSerItem());
         }
-        for (IMediaServerItem mediaServerItem : all) {
+        for (MediaServerItem mediaServerItem : all) {
             if (startGetMedia == null) startGetMedia = new HashMap<>();
             startGetMedia.put(mediaServerItem.getId(), true);
             new Thread(() -> {
                 ZLMServerConfig zlmServerConfig = getMediaServerConfig(mediaServerItem);
                 if (zlmServerConfig != null) {
+                    zlmServerConfig.setIp(mediaServerItem.getIp());
+                    zlmServerConfig.setHttpPort(mediaServerItem.getHttpPort());
                     startGetMedia.remove(mediaServerItem.getId());
                     mediaServerService.handLeZLMServerConfig(zlmServerConfig);
                 }
             }).start();
         }
         Timer timer = new Timer();
-        // 1鍒嗛挓鍚庢湭杩炴帴鍒板垯涓嶅啀鍘讳富鍔ㄨ繛鎺�
+        // 2鍒嗛挓鍚庢湭杩炴帴鍒板垯涓嶅啀鍘讳富鍔ㄨ繛鎺�, TODO 骞跺閲嶅惎鍓嶄娇鐢ㄦ鍦▃lm鐨勯�氶亾鍙戦�乥ye
         timer.schedule(new TimerTask() {
             @Override
             public void run() {
@@ -100,7 +106,7 @@
         }, 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;
         JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem);
         ZLMServerConfig ZLMServerConfig = null;
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/IMediaServerItem.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/IMediaServerItem.java
deleted file mode 100644
index 6497162..0000000
--- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/IMediaServerItem.java
+++ /dev/null
@@ -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);
-}
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java
index b56881f..d1578d1 100644
--- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java
@@ -1,10 +1,13 @@
 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 org.springframework.util.StringUtils;
 
-public class MediaServerItem implements IMediaServerItem{
+import java.util.HashMap;
+
+public class MediaServerItem{
 
     private String id;
 
@@ -46,9 +49,18 @@
 
     private String updateTime;
 
-    private boolean docker;
+    private boolean defaultServer;
 
-    private int count;
+    private SsrcConfig ssrcConfig;
+
+    private int currentPort;
+
+
+    /**
+     * 姣忎竴鍙癦LM閮芥湁涓�濂楃嫭绔嬬殑SSRC鍒楄〃
+     * 鍦ˋpplicationCheckRunner閲屽mediaServerSsrcMap杩涜鍒濆鍖�
+     */
+    private HashMap<String, SsrcConfig> mediaServerSsrcMap;
 
     public MediaServerItem() {
     }
@@ -218,14 +230,12 @@
         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() {
@@ -244,11 +254,29 @@
         this.updateTime = updateTime;
     }
 
-    public int getCount() {
-        return count;
+    public HashMap<String, SsrcConfig> getMediaServerSsrcMap() {
+        return mediaServerSsrcMap;
     }
 
-    public void setCount(int count) {
-        this.count = count;
+    public void setMediaServerSsrcMap(HashMap<String, SsrcConfig> mediaServerSsrcMap) {
+        this.mediaServerSsrcMap = mediaServerSsrcMap;
     }
+
+    public SsrcConfig getSsrcConfig() {
+        return ssrcConfig;
+    }
+
+    public void setSsrcConfig(SsrcConfig ssrcConfig) {
+        this.ssrcConfig = ssrcConfig;
+    }
+
+    public int getCurrentPort() {
+        return currentPort;
+    }
+
+    public void setCurrentPort(int currentPort) {
+        this.currentPort = currentPort;
+    }
+
+
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java b/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java
index 7a57bed..be9959a 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java
@@ -3,8 +3,8 @@
 import com.genersoft.iot.vmp.conf.MediaConfig;
 import com.genersoft.iot.vmp.gb28181.bean.Device;
 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.bean.SSRCInfo;
 
 import java.util.List;
 
@@ -13,11 +13,13 @@
  */
 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 @@
      */
     void handLeZLMServerConfig(ZLMServerConfig zlmServerConfig);
 
-    void updateServerCatch(IMediaServerItem mediaServerItem, Integer count, Boolean b);
+    MediaServerItem getMediaServerForMinimumLoad();
 
-    IMediaServerItem getMediaServerForMinimumLoad();
+    void setZLMConfig(MediaServerItem mediaServerItem);
 
-    void setZLMConfig(IMediaServerItem mediaServerItem);
-
-    void init();
+    SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId);
 
     void closeRTPServer(Device device, String channelId);
 
-    void update(MediaConfig mediaConfig);
+    void clearRTPServer(MediaServerItem mediaServerItem);
+
+    void update(MediaServerItem mediaSerItem);
 
     void addCount(String mediaServerId);
 
     void removeCount(String mediaServerId);
+
+    void releaseSsrc(MediaServerItem mediaServerItem, String ssrc);
+
+    void clearMediaServerForOnline();
+
+    void add(MediaServerItem mediaSerItem);
+
+    void resetOnlineServerItem(MediaServerItem serverItem);
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/service/IMediaService.java b/src/main/java/com/genersoft/iot/vmp/service/IMediaService.java
index 868a831..54f8315 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/IMediaService.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/IMediaService.java
@@ -2,7 +2,6 @@
 
 import com.alibaba.fastjson.JSONArray;
 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;
 
 /**
@@ -33,7 +32,7 @@
      * @param stream
      * @return
      */
-    StreamInfo getStreamInfoByAppAndStream(IMediaServerItem mediaServerItem, String app, String stream, JSONArray tracks);
+    StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaServerItem, String app, String stream, JSONArray tracks);
 
     /**
      * 鏍规嵁搴旂敤鍚嶅拰娴両D鑾峰彇鎾斁鍦板潃, 鍙槸鍦板潃鎷兼帴锛岃繑鍥炵殑ip浣跨敤杩滅▼璁块棶ip锛岄�傜敤涓巣lm涓巜vp鍦ㄤ竴鍙颁富鏈虹殑鎯呭喌
@@ -41,5 +40,5 @@
      * @param stream
      * @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);
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java b/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
index fdc86d6..9e5c444 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
@@ -4,7 +4,6 @@
 import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
 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.vmanager.gb28181.play.bean.PlayResult;
 
@@ -13,10 +12,10 @@
  */
 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);
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java b/src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java
index fa79d69..12e4898 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java
@@ -1,7 +1,6 @@
 package com.genersoft.iot.vmp.service;
 
 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.StreamProxyItem;
 import com.github.pagehelper.PageInfo;
@@ -63,5 +62,5 @@
      * 鑾峰彇ffmpeg.cmd妯℃澘
      * @return
      */
-    JSONObject getFFmpegCMDs(IMediaServerItem mediaServerItem);
+    JSONObject getFFmpegCMDs(MediaServerItem mediaServerItem);
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java b/src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java
index eaf2490..899da98 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java
@@ -1,7 +1,7 @@
 package com.genersoft.iot.vmp.service;
 
 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.github.pagehelper.PageInfo;
 
@@ -9,7 +9,7 @@
 
 public interface IStreamPushService {
 
-    List<StreamPushItem> handleJSON(String json, IMediaServerItem mediaServerItem);
+    List<StreamPushItem> handleJSON(String json, MediaServerItem mediaServerItem);
 
     /**
      * 灏嗗簲鐢ㄥ悕鍜屾祦ID鍔犲叆鍥芥爣鍏宠仈
diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/SSRCInfo.java b/src/main/java/com/genersoft/iot/vmp/service/bean/SSRCInfo.java
new file mode 100644
index 0000000..faab1c8
--- /dev/null
+++ b/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;
+    }
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
index 52c9f85..3d66665 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
@@ -1,29 +1,32 @@
 package com.genersoft.iot.vmp.service.impl;
 
-import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 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.ProxyServletConfig;
+import com.genersoft.iot.vmp.conf.SipConfig;
 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.media.zlm.ZLMRESTfulUtils;
 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
 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.ZLMRunInfo;
 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.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.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.core.annotation.Order;
 import org.springframework.stereotype.Service;
 
+import java.sql.Array;
 import java.text.SimpleDateFormat;
 import java.util.*;
 
@@ -31,15 +34,13 @@
  * 濯掍綋鏈嶅姟鍣ㄨ妭鐐圭鐞�
  */
 @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 Map<String, IMediaServerItem> zlmServers = new HashMap<>(); // 鎵�鏈夋暟鎹簱鐨剒lm鐨勭紦瀛�
-    private Map<String, Integer> zlmServerStatus = new LinkedHashMap<>(); // 鎵�鏈変笂绾跨殑zlm鐨勭紦瀛樹互鍙婅礋杞�
-
-    @Value("${sip.ip}")
-    private String sipIp;
+    @Autowired
+    private SipConfig sipConfig;
 
     @Value("${server.ssl.enabled:false}")
     private boolean sslEnabled;
@@ -56,7 +57,6 @@
     @Autowired
     private MediaServerMapper mediaServerMapper;
 
-
     @Autowired
     private IRedisCatchStorage redisCatchStorage;
 
@@ -66,53 +66,134 @@
     @Autowired
     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
-    public void init() {
-        zlmServers.clear();
-        zlmServerStatus.clear();
+    public void run(String... args) throws Exception {
+        logger.info("Media Server 缂撳瓨鍒濆鍖�");
         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鏄惁瀛樺湪姝ediaServer
+            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鍙敤鐨剆src
+        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
     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);
     }
 
     @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
+    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()
+                    )
+            );
+        }
+        String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerItemInDataBase.getId();
+        redisUtil.set(key, mediaServerItemInDataBase);
     }
 
     @Override
-    public List<IMediaServerItem> getAll() {
-        if (zlmServers.size() == 0) {
-            init();
-        }
-        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);
+    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 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,24 +202,26 @@
      * @return MediaServerItem
      */
     @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
-    public IMediaServerItem getOneByHostAndPort(String host, int port) {
+    public MediaServerItem getOneByHostAndPort(String host, int 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);
     }
 
     /**
@@ -150,111 +233,100 @@
         logger.info("[ {} ]-[ {}:{} ]宸茶繛鎺�",
                 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())) {
+            // 閰嶇疆鏂囦欢鐨剒lm
             // 濡傛灉鏄厤缃枃浠朵腑鐨剒lm銆� 涔熷氨鏄粯璁lm銆� 涓�鍒囦互閰嶇疆鏂囦欢鍐呭涓哄噯
-            // docker閮ㄧ讲涓嶄細浣跨敤zlm閰嶇疆鐨勭鍙e彿;
-            // 鐩存帴缂栬瘧閮ㄧ讲鐨勪娇鐢ㄩ厤缃枃浠剁殑绔彛鍙凤紝濡傛灉zlm淇敼閰嶆敼浜嗛厤缃紝wvp鑷姩淇敼
+            // docker閮ㄧ讲涓嶄細浣跨敤zlm閰嶇疆鐨勭鍙e彿涓嶆槸榛樿鐨勫垯涓嶅仛鏇存柊锛� 閰嶇疆淇敼闇�瑕佽嚜琛屼慨鏀箂erver閰嶇疆;
+            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){
+                // 鍙兘鏄悓涓�涓獄lm浣唅d鍙戠敓浜嗗彉鍖�
+                if (!serverItem.getId().equals(zlmServerConfig.getGeneralMediaServerId())) {
+                    mediaServerMapper.delOne(serverItem.getId());
+                    redisUtil.del(VideoManagerConstants.MEDIA_SERVER_PREFIX + serverItem.getId());
 
-            if (serverItem.getId().equals(mediaConfig.getId())
-                    || (serverItem.getIp().equals(mediaConfig.getIp()) && serverItem.getHttpPort() == mediaConfig.getHttpPort())) {
-                // 閰嶇疆鏂囦欢鐨剒lm
-                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());
-
+                    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);
+            }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 {
+            String now = this.format.format(new Date(System.currentTimeMillis()));
+            if (serverItem == null){
+                    // 涓�涓柊鐨剒lm鎺ュ叆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);
                 setZLMConfig(serverItem);
             }
-        }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 {
-                // 涓�涓柊鐨剒lm鎺ュ叆wvp
-                serverItem = new MediaServerItem(zlmServerConfig, sipIp);
-                serverItem.setCreateTime(now);
-                serverItem.setUpdateTime(now);
-                mediaServerMapper.add(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
-    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
     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
     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 @@
      * @return MediaServerItem
      */
     @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 (redisUtil.zSize(key)  == null || redisUtil.zSize(key) == 0) {
+            logger.info("鑾峰彇璐熻浇鏈�浣庣殑鑺傜偣鏃舵棤鍦ㄧ嚎鑺傜偣");
         }
 
-        if (key == null) {
-            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 @@
      * @param mediaServerItem 鏈嶅姟ID
      */
     @Override
-    public void setZLMConfig(IMediaServerItem mediaServerItem) {
+    public void setZLMConfig(MediaServerItem mediaServerItem) {
         logger.info("[ {} ]-[ {}:{} ]璁剧疆zlm",
                 mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
         String protocol = sslEnabled ? "https" : "http";
@@ -333,8 +388,10 @@
             logger.info("[ {} ]-[ {}:{} ]璁剧疆zlm鎴愬姛",
                     mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
         }else {
-            logger.info("[ {} ]-[ {}:{} ]璁剧疆zlm澶辫触" + responseJSON.getString("msg"),
+            logger.info("[ {} ]-[ {}:{} ]璁剧疆zlm澶辫触",
                     mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
         }
     }
+
+
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
index 465ca88..fb95861 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
@@ -4,9 +4,7 @@
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 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.dto.IMediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@@ -33,14 +31,14 @@
 
 
     @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);
     }
 
     @Override
     public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, String addr) {
         StreamInfo streamInfo = null;
-        IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
+        MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
         if (mediaInfo == null) {
             return streamInfo;
         }
@@ -63,7 +61,7 @@
     }
 
     @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();
         streamInfoResult.setStreamId(stream);
         streamInfoResult.setApp(app);
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
index 85a4f48..c21f599 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -14,11 +14,12 @@
 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.ZLMRESTfulUtils;
-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.bean.SSRCInfo;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 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.gb28181.play.bean.PlayResult;
 import com.genersoft.iot.vmp.service.IMediaService;
@@ -54,6 +55,9 @@
     private IRedisCatchStorage redisCatchStorage;
 
     @Autowired
+    private RedisUtil redis;
+
+    @Autowired
     private DeferredResultHolder resultHolder;
 
     @Autowired
@@ -73,7 +77,7 @@
 
 
     @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();
         if (mediaServerItem == null) {
             RequestMessage msg = new RequestMessage();
@@ -97,14 +101,21 @@
         // 瓒呮椂澶勭悊
         result.onTimeout(()->{
             logger.warn(String.format("璁惧鐐规挱瓒呮椂锛宒eviceId锛�%s 锛宑hannelId锛�%s", deviceId, channelId));
-            // 閲婃斁rtpserver
-            mediaServerService.closeRTPServer(playResult.getDevice(), channelId);
             RequestMessage msg = new RequestMessage();
             msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + playResult.getUuid());
             WVPResult wvpResult = new WVPResult();
             wvpResult.setCode(-1);
-            wvpResult.setMsg("Timeout");
+            SIPDialog dialog = streamSession.getDialog(deviceId, channelId);
+            if (dialog != null) {
+                wvpResult.setMsg("鏀舵祦瓒呮椂锛岃绋嶅�欓噸璇�");
+            }else {
+                wvpResult.setMsg("鐐规挱瓒呮椂锛岃绋嶅�欓噸璇�");
+            }
             msg.setData(wvpResult);
+            // 鐐规挱瓒呮椂鍥炲BYE
+            cmder.streamByeCmd(device.getDeviceId(), channelId);
+            // 閲婃斁rtpserver
+            mediaServerService.closeRTPServer(playResult.getDevice(), channelId);
             resultHolder.invokeResult(msg);
         });
         result.onCompletion(()->{
@@ -131,7 +142,7 @@
                     WVPResult wvpResult = (WVPResult)responseEntity.getBody();
                     if (wvpResult.getCode() == 0) {
                         StreamInfo streamInfoForSuccess = (StreamInfo)wvpResult.getData();
-                        IMediaServerItem mediaInfo = mediaServerService.getOne(streamInfoForSuccess.getMediaServerId());
+                        MediaServerItem mediaInfo = mediaServerService.getOne(streamInfoForSuccess.getMediaServerId());
                         String streamUrl = streamInfoForSuccess.getFmp4();
                         // 璇锋眰鎴浘
                         zlmresTfulUtils.getSnap(mediaInfo, streamUrl, 15, 1, path, fileName);
@@ -142,14 +153,23 @@
             }
         });
         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());
                 onPublishHandlerForPlay(mediaServerItemInUse, response, deviceId, channelId, uuid.toString());
                 if (hookEvent != null) {
                     hookEvent.response(mediaServerItem, response);
                 }
             }, (event) -> {
+                // 鐐规挱杩斿洖sip閿欒
                 RequestMessage msg = new RequestMessage();
                 msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
                 Response response = event.getResponse();
@@ -162,6 +182,7 @@
                 if (errorEvent != null) {
                     errorEvent.response(event);
                 }
+
             });
         } else {
             String streamId = streamInfo.getStreamId();
@@ -176,7 +197,7 @@
                 return playResult;
             }
             String mediaServerId = streamInfo.getMediaServerId();
-            IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
+            MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
 
             JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId);
             if (rtpInfo != null && rtpInfo.getBoolean("exist")) {
@@ -194,9 +215,17 @@
                     hookEvent.response(mediaServerItem, JSONObject.parseObject(JSON.toJSONString(streamInfo)));
                 }
             } else {
+                // TODO 鐐规挱鍓嶆槸鍚﹂噸缃姸鎬�
                 redisCatchStorage.stopPlay(streamInfo);
                 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());
                     onPublishHandlerForPlay(mediaServerItemInuse, response, deviceId, channelId, uuid.toString());
                 }, (event) -> {
@@ -218,7 +247,7 @@
     }
 
     @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();
         msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
         StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid);
@@ -228,14 +257,6 @@
                 deviceChannel.setStreamId(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);
             msg.setData(JSON.toJSONString(streamInfo));
 
@@ -254,10 +275,10 @@
     }
 
     @Override
-    public IMediaServerItem getNewMediaServerItem(Device device) {
+    public MediaServerItem getNewMediaServerItem(Device device) {
         if (device == null) return null;
         String mediaServerId = device.getMediaServerId();
-        IMediaServerItem mediaServerItem = null;
+        MediaServerItem mediaServerItem = null;
         if (mediaServerId == null) {
             mediaServerItem = mediaServerService.getMediaServerForMinimumLoad();
         }else {
@@ -270,7 +291,7 @@
     }
 
     @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();
         msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
         StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid);
@@ -285,7 +306,7 @@
         }
     }
 
-    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");
         JSONArray tracks = resonse.getJSONArray("tracks");
         StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem,"rtp", streamId, tracks);
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
index fe49c3b..bbcad1c 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
@@ -3,7 +3,6 @@
 import com.alibaba.fastjson.JSONObject;
 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
 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.StreamProxyItem;
 import com.genersoft.iot.vmp.service.IGbStreamService;
@@ -58,7 +57,7 @@
 
     @Override
     public String save(StreamProxyItem param) {
-        IMediaServerItem mediaInfo;
+        MediaServerItem mediaInfo;
         if ("auto".equals(param.getMediaServerId())){
             mediaInfo = mediaServerService.getMediaServerForMinimumLoad();
         }else {
@@ -120,7 +119,7 @@
     @Override
     public JSONObject addStreamProxyToZlm(StreamProxyItem param) {
         JSONObject result = null;
-        IMediaServerItem mediaServerItem = null;
+        MediaServerItem mediaServerItem = null;
         if (param.getMediaServerId() == null) {
             logger.warn("娣诲姞浠g悊鏃禡ediaServerId 涓簄ull");
             return null;
@@ -141,7 +140,7 @@
     @Override
     public JSONObject removeStreamProxyFromZlm(StreamProxyItem param) {
         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());
         return result;
     }
@@ -198,7 +197,7 @@
     }
 
     @Override
-    public JSONObject getFFmpegCMDs(IMediaServerItem mediaServerItem) {
+    public JSONObject getFFmpegCMDs(MediaServerItem mediaServerItem) {
         JSONObject result = new JSONObject();
         JSONObject mediaServerConfigResuly = zlmresTfulUtils.getMediaServerConfig(mediaServerItem);
         if (mediaServerConfigResuly != null && mediaServerConfigResuly.getInteger("code") == 0
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java
index 3692e54..aabf35f 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java
@@ -5,7 +5,6 @@
 import com.alibaba.fastjson.TypeReference;
 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
 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.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
@@ -43,7 +42,7 @@
     private IMediaServerService mediaServerService;
 
     @Override
-    public List<StreamPushItem> handleJSON(String jsonData, IMediaServerItem mediaServerItem) {
+    public List<StreamPushItem> handleJSON(String jsonData, MediaServerItem mediaServerItem) {
         if (jsonData == null) return null;
 
         Map<String, StreamPushItem> result = new HashMap<>();
@@ -98,7 +97,7 @@
     @Override
     public boolean removeFromGB(GbStream stream) {
         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());
         if (mediaList == null) {
             streamPushMapper.del(stream.getApp(), stream.getStream());
diff --git a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
index a4edb08..f5b2b1b 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
@@ -5,8 +5,6 @@
 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
 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.Map;
diff --git a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java
index 97c3794..223a5e8 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java
@@ -3,7 +3,6 @@
 import java.util.List;
 
 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.StreamProxyItem;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java
index 475ec6d..16ed401 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java
@@ -1,7 +1,5 @@
 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 org.apache.ibatis.annotations.Insert;
 import org.apache.ibatis.annotations.Mapper;
@@ -35,6 +33,7 @@
             "rtpEnable, " +
             "rtpPortRange, " +
             "recordAssistPort, " +
+            "defaultServer, " +
             "createTime, " +
             "updateTime" +
             ") VALUES " +
@@ -57,9 +56,10 @@
             "${rtpEnable}, " +
             "'${rtpPortRange}', " +
             "${recordAssistPort}, " +
+            "${defaultServer}, " +
             "'${createTime}', " +
             "'${updateTime}')")
-    int add(IMediaServerItem mediaServerItem);
+    int add(MediaServerItem mediaServerItem);
 
     @Update(value = {" <script>" +
             "UPDATE media_server " +
@@ -83,7 +83,7 @@
             "<if test=\"recordAssistPort != null\">, recordAssistPort=${recordAssistPort}</if>" +
             "WHERE id='${id}'"+
             " </script>"})
-    int update(IMediaServerItem mediaServerItem);
+    int update(MediaServerItem mediaServerItem);
 
     @Select("SELECT * FROM media_server WHERE id='${id}'")
     MediaServerItem queryOne(String id);
@@ -92,7 +92,7 @@
     List<MediaServerItem> queryAll();
 
     @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}")
     MediaServerItem queryOneByHostAndPort(String host, int port);
diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
index eafb8a0..08eb9d1 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
@@ -3,10 +3,7 @@
 import com.alibaba.fastjson.JSONObject;
 import com.genersoft.iot.vmp.common.StreamInfo;
 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.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.dao.DeviceChannelMapper;
 import com.genersoft.iot.vmp.utils.redis.RedisUtil;
diff --git a/src/main/java/com/genersoft/iot/vmp/utils/ConfigConst.java b/src/main/java/com/genersoft/iot/vmp/utils/ConfigConst.java
new file mode 100644
index 0000000..125d818
--- /dev/null
+++ b/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;
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/utils/SerializeUtils.java b/src/main/java/com/genersoft/iot/vmp/utils/SerializeUtils.java
new file mode 100644
index 0000000..ae91ad5
--- /dev/null
+++ b/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;
+    }
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/utils/redis/JedisUtil.java b/src/main/java/com/genersoft/iot/vmp/utils/redis/JedisUtil.java
new file mode 100644
index 0000000..54e5422
--- /dev/null
+++ b/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();
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java b/src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java
index 5db3c7f..dd5614f 100644
--- a/src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java
+++ b/src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java
@@ -415,10 +415,10 @@
      *
      * @param key
      * @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);
     }
 
     /**
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
index aae9cce..d6545b5 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
@@ -2,13 +2,12 @@
 
 import com.alibaba.fastjson.JSONArray;
 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.media.zlm.ZLMServerConfig;
 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.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.service.IMediaServerService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@@ -37,7 +36,7 @@
 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
 import org.springframework.web.context.request.async.DeferredResult;
 
-import java.util.Enumeration;
+import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 
@@ -89,7 +88,7 @@
 
 		// 鑾峰彇鍙敤鐨剒lm
 		Device device = storager.queryVideoDevice(deviceId);
-		IMediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
+		MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
 		PlayResult playResult = playService.play(newMediaServerItem, deviceId, channelId, null, null);
 
 		return playResult.getResult();
@@ -174,7 +173,7 @@
 			logger.warn("瑙嗛杞爜API璋冪敤澶辫触锛�, 瑙嗛娴佸凡缁忓仠姝�!");
 			return new ResponseEntity<String>("鏈壘鍒拌棰戞祦淇℃伅, 瑙嗛娴佸彲鑳藉凡缁忓仠姝�", HttpStatus.OK);
 		}
-		IMediaServerItem mediaInfo = mediaServerService.getOne(streamInfo.getMediaServerId());
+		MediaServerItem mediaInfo = mediaServerService.getOne(streamInfo.getMediaServerId());
 		JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId);
 		if (!rtpInfo.getBoolean("exist")) {
 			logger.warn("瑙嗛杞爜API璋冪敤澶辫触锛�, 瑙嗛娴佸凡鍋滄鎺ㄦ祦!");
@@ -219,7 +218,7 @@
 			result.put("msg", "mediaServerId is null");
 			return new ResponseEntity<String>( result.toJSONString(), HttpStatus.BAD_REQUEST);
 		}
-		IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
+		MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
 		if (mediaInfo == null) {
 			result.put("code", 0);
 			result.put("msg", "浣跨敤鐨勬祦濯掍綋宸茬粡鍋滄杩愯");
@@ -307,16 +306,16 @@
 			logger.debug("鑾峰彇鎵�鏈夌殑ssrc");
 		}
 		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();
-			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);
 		}
+
 		WVPResult<JSONObject> result = new WVPResult<>();
 		result.setCode(0);
 		result.setMsg("success");
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java
index 218debf..2ca4aba 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java
@@ -3,9 +3,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.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.service.IMediaServerService;
+import com.genersoft.iot.vmp.service.bean.SSRCInfo;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.service.IPlayService;
 import io.swagger.annotations.Api;
@@ -58,6 +58,9 @@
 	@Autowired
 	private DeferredResultHolder resultHolder;
 
+	@Autowired
+	private IMediaServerService mediaServerService;
+
 	@ApiOperation("寮�濮嬪巻鍙插獟浣撲笅杞�")
 	@ApiImplicitParams({
 			@ApiImplicitParam(name = "deviceId", value = "璁惧ID", dataTypeClass = String.class),
@@ -90,7 +93,7 @@
 			cmder.streamByeCmd(deviceId, channelId);
 		}
 		resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result);
-		IMediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
+		MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
 		if (newMediaServerItem == null) {
 			logger.warn(String.format("璁惧涓嬭浇鍝嶅簲瓒呮椂锛宒eviceId锛�%s 锛宑hannelId锛�%s", deviceId, channelId));
 			RequestMessage msg = new RequestMessage();
@@ -99,7 +102,10 @@
 			resultHolder.invokeResult(msg);
 			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());
 			playService.onPublishHandlerForPlayBack(mediaServerItem, response, deviceId, channelId, uuid.toString());
 		}, event -> {
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java
index d2a30fa..9fd05b2 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java
@@ -4,8 +4,9 @@
 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
 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.service.IMediaServerService;
+import com.genersoft.iot.vmp.service.bean.SSRCInfo;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.service.IPlayService;
 import io.swagger.annotations.Api;
@@ -58,6 +59,9 @@
 	@Autowired
 	private DeferredResultHolder resultHolder;
 
+	@Autowired
+	private IMediaServerService mediaServerService;
+
 	@ApiOperation("寮�濮嬭棰戝洖鏀�")
 	@ApiImplicitParams({
 			@ApiImplicitParam(name = "deviceId", value = "璁惧ID", dataTypeClass = String.class),
@@ -74,6 +78,15 @@
 		}
 		UUID uuid = UUID.randomUUID();
 		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(()->{
 			logger.warn(String.format("璁惧鍥炴斁瓒呮椂锛宒eviceId锛�%s 锛宑hannelId锛�%s", deviceId, channelId));
@@ -82,14 +95,14 @@
 			msg.setData("Timeout");
 			resultHolder.invokeResult(msg);
 		});
-		Device device = storager.queryVideoDevice(deviceId);
+
 		StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, channelId);
 		if (streamInfo != null) {
 			// 鍋滄涔嬪墠鐨勫洖鏀�
 			cmder.streamByeCmd(deviceId, channelId);
 		}
 		resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result);
-		IMediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
+
 		if (newMediaServerItem == null) {
 			logger.warn(String.format("璁惧鍥炴斁瓒呮椂锛宒eviceId锛�%s 锛宑hannelId锛�%s", deviceId, channelId));
 			RequestMessage msg = new RequestMessage();
@@ -98,7 +111,8 @@
 			resultHolder.invokeResult(msg);
 			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());
 			playService.onPublishHandlerForPlayBack(mediaServerItem, response, deviceId, channelId, uuid.toString());
 		}, event -> {
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/session/PlayTypeEnum.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/session/PlayTypeEnum.java
new file mode 100644
index 0000000..58fbb26
--- /dev/null
+++ b/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;
+    }
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java
index 45eeac8..76ad86c 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java
@@ -1,10 +1,8 @@
 package com.genersoft.iot.vmp.vmanager.server;
 
 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.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.utils.SpringBeanFactory;
 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
 import gov.nist.javax.sip.SipStackImpl;
@@ -17,7 +15,6 @@
 import javax.sip.ListeningPoint;
 import javax.sip.ObjectInUseException;
 import javax.sip.SipProvider;
-import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
@@ -38,19 +35,30 @@
     @ApiOperation("娴佸獟浣撴湇鍔″垪琛�")
     @GetMapping(value = "/media_server/list")
     @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.setMsg("success");
         result.setData(mediaServerService.getAll());
         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("鑾峰彇娴佸獟浣撴湇鍔�")
     @GetMapping(value = "/media_server/one/{id}")
     @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.setMsg("success");
         result.setData(mediaServerService.getOne(id));
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java
index f099631..f8c01dd 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java
@@ -1,7 +1,6 @@
 package com.genersoft.iot.vmp.vmanager.streamProxy;
 
 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.StreamProxyItem;
 import com.genersoft.iot.vmp.service.IMediaServerService;
@@ -9,7 +8,6 @@
 import com.genersoft.iot.vmp.service.IStreamProxyService;
 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
 import com.github.pagehelper.PageInfo;
-import io.netty.util.internal.StringUtil;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
@@ -86,7 +84,7 @@
     public WVPResult getFFmpegCMDs(@RequestParam String mediaServerId){
         logger.debug("鑾峰彇鑺傜偣[ {} ]ffmpeg.cmd妯℃澘", mediaServerId );
 
-        IMediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
+        MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
         JSONObject data = streamProxyService.getFFmpegCMDs(mediaServerItem);
         WVPResult<JSONObject> result = new WVPResult<>();
         result.setCode(0);
diff --git a/src/main/resources/all-application.yml b/src/main/resources/all-application.yml
index 2552e01..c4bd7ca 100644
--- a/src/main/resources/all-application.yml
+++ b/src/main/resources/all-application.yml
@@ -17,6 +17,12 @@
         password:
         # [鍙�塢 瓒呮椂鏃堕棿
         timeout: 10000
+        # [鍙�塢 涓�涓猵ool鏈�澶氬彲鍒嗛厤澶氬皯涓猨edis瀹炰緥
+        poolMaxTotal: 1000
+        # [鍙�塢 涓�涓猵ool鏈�澶氭湁澶氬皯涓姸鎬佷负idle(绌洪棽)鐨刯edis瀹炰緥
+        poolMaxIdle: 500
+        # [鍙�塢 鏈�澶х殑绛夊緟鏃堕棿(绉�)
+        poolMaxWait: 5
     # [鍙�塢 jdbc鏁版嵁搴撻厤缃�, 椤圭洰浣跨敤sqlite浣滀负鏁版嵁搴擄紝涓�鑸笉闇�瑕侀厤缃�
     datasource:
         # 浣跨敤mysql 鎵撳紑23-28琛屾敞閲婏紝 鍒犻櫎29-36琛�
@@ -124,6 +130,7 @@
     level:
         com.genersoft.iot: debug
         com.genersoft.iot.vmp.storager.dao: info
+        com.genersoft.iot.vmp.gb28181: info
 # [鏍规嵁涓氬姟闇�姹傞厤缃甝
 user-settings:
     # [鍙�塢 鑷姩鐐规挱锛� 浣跨敤鍥哄畾娴佸湴鍧�杩涜鎾斁鏃讹紝濡傛灉鏈偣鎾垯鑷姩杩涜鐐规挱, 闇�瑕乺tp.enable=true
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index b756be9..dd2e0f7 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -76,6 +76,8 @@
     level:
         com.genersoft.iot: debug
         com.genersoft.iot.vmp.storager.dao: info
+        com.genersoft.iot.vmp.gb28181: info
+
 # [鏍规嵁涓氬姟闇�姹傞厤缃甝
 user-settings:
     # 鎺ㄦ祦鐩存挱鏄惁褰曞埗
diff --git a/src/main/resources/wvp.sqlite b/src/main/resources/wvp.sqlite
index 8e41983..500607c 100644
--- a/src/main/resources/wvp.sqlite
+++ b/src/main/resources/wvp.sqlite
Binary files differ
diff --git a/web_src/src/components/service/MediaServer.js b/web_src/src/components/service/MediaServer.js
index a63d19c..b905352 100644
--- a/web_src/src/components/service/MediaServer.js
+++ b/web_src/src/components/service/MediaServer.js
@@ -9,7 +9,7 @@
   getMediaServerList(callback){
     this.$axios({
       method: 'get',
-      url:`/api/server/media_server/list`,
+      url:`/api/server/media_server/online/list`,
     }).then(function (res) {
       if (typeof (callback) == "function") callback(res.data)
     }).catch(function (error) {

--
Gitblit v1.8.0