From 7dc8fd4a1e8c5afb6fad53454935419c239838c0 Mon Sep 17 00:00:00 2001
From: panlinlin <648540858@qq.com>
Date: 星期四, 01 四月 2021 18:06:21 +0800
Subject: [PATCH] 添加拉流代理与国标关联, 支持代理rtsp/rtmp/...,转发到国标

---
 src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java                          |   13 
 src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java                              |    9 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java                |    4 
 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java                         |   47 +
 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyItem.java                         |    7 
 src/main/java/com/genersoft/iot/vmp/storager/dao/PlarfotmGbStreamMapper.java                   |   28 +
 src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformChannelMapper.java                    |    2 
 src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java                                     |    9 
 web_src/src/components/PushVideoList.vue                                                       |   21 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java     |   17 
 web_src/src/components/dialog/chooseChannelForGb.vue                                           |    2 
 src/main/java/com/genersoft/iot/vmp/vmanager/service/IGbStreamService.java                     |   41 +
 src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/GbStreamServiceImpl.java             |   89 +++
 src/main/java/com/genersoft/iot/vmp/vmanager/gbStream/GbStreamController.java                  |   65 ++
 web_src/src/components/dialog/devicePlayer.vue                                                 |    7 
 src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java                 |   19 
 src/main/java/com/genersoft/iot/vmp/vmanager/platformGbStream/PlatformGbStreamController.java  |   35 +
 src/main/java/com/genersoft/iot/vmp/vmanager/gbStream/bean/GbStreamParam.java                  |   28 +
 web_src/src/components/PLatformStreamList.vue                                                  |  283 ++++++++++
 web_src/src/components/dialog/StreamProxyEdit.vue                                              |   11 
 src/main/java/com/genersoft/iot/vmp/vmanager/service/IStreamProxyService.java                  |   11 
 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java                                   |    6 
 web_src/src/components/StreamProxyList.vue                                                     |    7 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java     |    4 
 src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformGbStream.java                         |   31 +
 web_src/src/components/ParentPlatformList.vue                                                  |    2 
 src/main/java/com/genersoft/iot/vmp/vmanager/media/MediaController.java                        |    3 
 src/main/resources/wvp.sqlite                                                                  |    0 
 src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java            |   13 
 src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java                |  102 ++
 web_src/src/components/dialog/chooseChannelForStream.vue                                       |  215 +++++++
 src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java                        |   34 
 web_src/src/components/dialog/chooseChannel.vue                                                |    8 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java  |  181 ++++--
 src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/StreamProxyServiceImpl.java          |   56 +
 src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java                        |   18 
 src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/MediaServiceImpl.java                |    2 
 src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbStream.java                                 |   71 ++
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java     |   30 
 web_src/src/router/index.js                                                                    |    5 
 src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java                           |   49 +
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java |   33 +
 42 files changed, 1,394 insertions(+), 224 deletions(-)

diff --git a/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java b/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
index 0082a27..1c24eb9 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
@@ -4,6 +4,7 @@
 
 public class StreamInfo {
 
+    private String app;
     private String streamId;
     private String deviceID;
     private String channelId;
@@ -19,6 +20,14 @@
     private String rtsp;
     private JSONArray tracks;
 
+    public String getApp() {
+        return app;
+    }
+
+    public void setApp(String app) {
+        this.app = app;
+    }
+
     public String getDeviceID() {
         return deviceID;
     }
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbStream.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbStream.java
new file mode 100644
index 0000000..8fb1980
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbStream.java
@@ -0,0 +1,71 @@
+package com.genersoft.iot.vmp.gb28181.bean;
+
+/**
+ * 鐩存挱娴佸叧鑱斿浗鏍囦笂绾у钩鍙�
+ */
+public class GbStream extends PlatformGbStream{
+
+    private String app;
+    private String stream;
+    private String gbId;
+    private String name;
+    private double longitude;
+    private double latitude;
+    private String streamType;
+
+    public String getApp() {
+        return app;
+    }
+
+    public void setApp(String app) {
+        this.app = app;
+    }
+
+    public String getStream() {
+        return stream;
+    }
+
+    public void setStream(String stream) {
+        this.stream = stream;
+    }
+
+    public String getGbId() {
+        return gbId;
+    }
+
+    public void setGbId(String gbId) {
+        this.gbId = gbId;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public double getLongitude() {
+        return longitude;
+    }
+
+    public void setLongitude(double longitude) {
+        this.longitude = longitude;
+    }
+
+    public double getLatitude() {
+        return latitude;
+    }
+
+    public void setLatitude(double latitude) {
+        this.latitude = latitude;
+    }
+
+    public String getStreamType() {
+        return streamType;
+    }
+
+    public void setStreamType(String streamType) {
+        this.streamType = streamType;
+    }
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformGbStream.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformGbStream.java
new file mode 100644
index 0000000..a4871ae
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformGbStream.java
@@ -0,0 +1,31 @@
+package com.genersoft.iot.vmp.gb28181.bean;
+
+public class PlatformGbStream {
+    private String app;
+    private String stream;
+    private String platformId;
+
+    public String getApp() {
+        return app;
+    }
+
+    public void setApp(String app) {
+        this.app = app;
+    }
+
+    public String getStream() {
+        return stream;
+    }
+
+    public void setStream(String stream) {
+        this.stream = stream;
+    }
+
+    public String getPlatformId() {
+        return platformId;
+    }
+
+    public void setPlatformId(String platformId) {
+        this.platformId = platformId;
+    }
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java
index e0220dc..15e6f1e 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java
@@ -27,6 +27,11 @@
      */
     private String deviceId;
 
+    /**
+     * 鐩存挱娴佺殑搴旂敤鍚�
+     */
+    private String app;
+
    /**
      * 閫氶亾id
      */
@@ -40,10 +45,6 @@
      */
     private int status = 0;
 
-    /**
-     * 璁惧鎺ㄦ祦鐨刟pp
-     */
-    private String app = "rtp";
 
     /**
      * 璁惧鎺ㄦ祦鐨剆treamId
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 313348e..579e168 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
@@ -91,7 +91,9 @@
 	@Autowired
 	private SipSubscribe sipSubscribe;
 
-
+	public SipConfig getSipConfig() {
+		return sipConfig;
+	}
 
 	/**
 	 * 浜戝彴鏂瑰悜鏀炬帶鍒讹紝浣跨敤閰嶇疆鏂囦欢涓殑榛樿闀滃ご绉诲姩閫熷害
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
index 0892526..7945dcd 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
@@ -197,7 +197,7 @@
     @Override
     public boolean catalogQuery(DeviceChannel channel, ParentPlatform parentPlatform, String sn, String fromTag, int size) {
 
-        if (channel == null  || parentPlatform ==null) {
+        if ( parentPlatform ==null) {
             return false;
         }
         try {
@@ -210,20 +210,22 @@
             catalogXml.append("<SumNum>" + size + "</SumNum>\r\n");
             catalogXml.append("<DeviceList Num=\"1\">\r\n");
             catalogXml.append("<Item>\r\n");
+            if (channel != null) {
+                catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
+                catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n");
+                catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
+                catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
+                catalogXml.append("<Owner>" + channel.getOwner() + "</Owner>\r\n");
+                catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n");
+                catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
+                catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");// TODO 褰撳墠涓嶈兘娣诲姞鍒嗙粍锛� 鎵�浠ユ殏鏃舵病鏈夌埗鑺傜偣
+                catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n"); // TODO 褰撳墠涓嶈兘娣诲姞鍒嗙粍锛� 鎵�浠ユ殏鏃舵病鏈夌埗鑺傜偣
+                catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
+                catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
+                catalogXml.append("<Status>" + (channel.getStatus() == 0?"OFF":"ON") + "</Status>\r\n");
+                catalogXml.append("<Info></Info>\r\n");
+            }
 
-            catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
-            catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n");
-            catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
-            catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
-            catalogXml.append("<Owner>" + channel.getOwner() + "</Owner>\r\n");
-            catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n");
-            catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
-            catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");// TODO 褰撳墠涓嶈兘娣诲姞鍒嗙粍锛� 鎵�浠ユ殏鏃舵病鏈夌埗鑺傜偣
-            catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n"); // TODO 褰撳墠涓嶈兘娣诲姞鍒嗙粍锛� 鎵�浠ユ殏鏃舵病鏈夌埗鑺傜偣
-            catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
-            catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
-            catalogXml.append("<Status>" + (channel.getStatus() == 0?"OFF":"ON") + "</Status>\r\n");
-            catalogXml.append("<Info></Info>\r\n");
 
             catalogXml.append("</Item>\r\n");
             catalogXml.append("</DeviceList>\r\n");
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 20e1c80..00f1f7d 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
@@ -43,14 +43,23 @@
 			SendRtpItem sendRtpItem =  redisCatchStorage.querySendRTPServer(platformGbId, channelId);
 			String is_Udp = sendRtpItem.isTcp() ? "0" : "1";
 			String deviceId = sendRtpItem.getDeviceId();
-			StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
-			sendRtpItem.setStreamId(streamInfo.getStreamId());
+			StreamInfo streamInfo = null;
+			if (deviceId == null) {
+				streamInfo = new StreamInfo();
+				streamInfo.setApp(sendRtpItem.getApp());
+				streamInfo.setStreamId(sendRtpItem.getStreamId());
+			}else {
+				streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
+				sendRtpItem.setStreamId(streamInfo.getStreamId());
+				streamInfo.setApp("rtp");
+			}
+
 			redisCatchStorage.updateSendRTPSever(sendRtpItem);
 			System.out.println(platformGbId);
 			System.out.println(channelId);
 			Map<String, Object> param = new HashMap<>();
 			param.put("vhost","__defaultVhost__");
-			param.put("app","rtp");
+			param.put("app",streamInfo.getApp());
 			param.put("stream",streamInfo.getStreamId());
 			param.put("ssrc", sendRtpItem.getSsrc());
 			param.put("dst_url",sendRtpItem.getIp());
@@ -63,7 +72,7 @@
 			while (!rtpPushed) {
 				try {
 					if (System.currentTimeMillis() - startTime < 30 * 1000) {
-						if (zlmrtpServerFactory.isRtpReady(streamInfo.getStreamId())) {
+						if (zlmrtpServerFactory.isStreamReady(streamInfo.getApp(), streamInfo.getStreamId())) {
 							rtpPushed = true;
 							System.out.println("宸茶幏鍙栬澶囨帹娴侊紝寮�濮嬪悜涓婄骇鎺ㄦ祦");
 							zlmrtpServerFactory.startSendRtpStream(param);
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 c96501d..ec5f921 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
@@ -51,12 +51,12 @@
 				String streamId = sendRtpItem.getStreamId();
 				Map<String, Object> param = new HashMap<>();
 				param.put("vhost","__defaultVhost__");
-				param.put("app","rtp");
+				param.put("app",sendRtpItem.getApp());
 				param.put("stream",streamId);
 				System.out.println("鍋滄鍚戜笂绾ф帹娴侊細" + streamId);
 				zlmrtpServerFactory.stopSendRtpStream(param);
 				redisCatchStorage.deleteSendRTPServer(platformGbId, channelId);
-				if (zlmrtpServerFactory.totalReaderCount(streamId) == 0) {
+				if (zlmrtpServerFactory.totalReaderCount(sendRtpItem.getApp(), streamId) == 0) {
 					System.out.println(streamId + "鏃犲叾瀹冭鐪嬭�咃紝閫氱煡璁惧鍋滄鎺ㄦ祦");
 					cmder.streamByeCmd(streamId);
 				}
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 a7b3d94..15d0638 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
@@ -12,13 +12,12 @@
 import javax.sip.message.Response;
 
 import com.genersoft.iot.vmp.conf.MediaServerConfig;
-import com.genersoft.iot.vmp.gb28181.bean.Device;
-import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
-import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
-import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
+import com.genersoft.iot.vmp.gb28181.bean.*;
+import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
 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.ZLMHttpHookSubscribe;
 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
@@ -30,6 +29,8 @@
 import org.slf4j.LoggerFactory;
 
 import java.text.ParseException;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Vector;
 
 /**    
@@ -93,12 +94,14 @@
 			if (platform != null) {
 				// 鏌ヨ骞冲彴涓嬫槸鍚︽湁璇ラ�氶亾
 				DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId);
-				if (channel == null) {
+				GbStream gbStream = storager.queryStreamInParentPlatform(requesterId, channelId);
+				// 涓嶆槸閫氶亾鍙兘鏄洿鎾祦
+				if (channel != null || gbStream != null ) {
+					responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 閫氶亾瀛樺湪锛屽彂181锛屽懠鍙浆鎺ヤ腑
+				}else {
 					logger.info("閫氶亾涓嶅瓨鍦紝杩斿洖404");
 					responseAck(evt, Response.NOT_FOUND); // 閫氶亾涓嶅瓨鍦紝鍙�404锛岃祫婧愪笉瀛樺湪
 					return;
-				}else {
-					responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 閫氶亾瀛樺湪锛屽彂181锛屽懠鍙浆鎺ヤ腑
 				}
 				// 瑙f瀽sdp娑堟伅, 浣跨敤jainsip 鑷甫鐨剆dp瑙f瀽鏂瑰紡
 				String contentString = new String(request.getRawContent());
@@ -153,67 +156,120 @@
 				String addressStr = sdp.getOrigin().getAddress();
 				//String sessionName = sdp.getSessionName().getValue();
 				logger.info("[涓婄骇鐐规挱]鐢ㄦ埛锛歿}锛� 鍦板潃锛歿}:{}锛� ssrc锛歿}", username, addressStr, port, ssrc);
+				Device device  = null;
+				// 閫氳繃 channel 鍜� gbStream 鏄惁涓簄ull 鍊煎垽鏂潵婧愭槸鐩存挱娴佸悎閫傚浗鏍�
+				if (channel != null) {
+					device = storager.queryVideoDeviceByPlatformIdAndChannelId(requesterId, channelId);
+					if (device == null) {
+						logger.warn("鐐规挱骞冲彴{}鐨勯�氶亾{}鏃舵湭鎵惧埌璁惧淇℃伅", requesterId, channel);
+						responseAck(evt, Response.SERVER_INTERNAL_ERROR);
+						return;
+					}
+					SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(addressStr, port, ssrc, requesterId,
+							device.getDeviceId(), channelId,
+							mediaTransmissionTCP);
+					if (tcpActive != null) {
+						sendRtpItem.setTcpActive(tcpActive);
+					}
+					if (sendRtpItem == null) {
+						logger.warn("鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�");
+						responseAck(evt, Response.BUSY_HERE);
+						return;
+					}
 
-				Device device = storager.queryVideoDeviceByPlatformIdAndChannelId(requesterId, channelId);
-				if (device == null) {
-					logger.warn("鐐规挱骞冲彴{}鐨勯�氶亾{}鏃舵湭鎵惧埌璁惧淇℃伅", requesterId, channel);
-					responseAck(evt, Response.SERVER_INTERNAL_ERROR);
-					return;
-				}
-				SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(addressStr, port, ssrc, requesterId, device.getDeviceId(), channelId,
-						mediaTransmissionTCP);
-				if (tcpActive != null) {
-					sendRtpItem.setTcpActive(tcpActive);
-				}
-				if (sendRtpItem == null) {
-					logger.warn("鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�");
-					responseAck(evt, Response.BUSY_HERE);
-					return;
-				}
-
-				// 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶�
-				redisCatchStorage.updateSendRTPSever(sendRtpItem);
-				// 閫氱煡涓嬬骇鎺ㄦ祦锛�
-				PlayResult playResult = playService.play(device.getDeviceId(), channelId, (responseJSON)->{
-					// 鏀跺埌鎺ㄦ祦锛� 鍥炲200OK, 绛夊緟ack
-					sendRtpItem.setStatus(1);
+					// 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶�
 					redisCatchStorage.updateSendRTPSever(sendRtpItem);
-					// TODO 娣诲姞瀵箃cp鐨勬敮鎸�
-					MediaServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
-					StringBuffer content = new StringBuffer(200);
-					content.append("v=0\r\n");
-					content.append("o="+"00000"+" 0 0 IN IP4 "+mediaInfo.getWanIp()+"\r\n");
-					content.append("s=Play\r\n");
-					content.append("c=IN IP4 "+mediaInfo.getWanIp()+"\r\n");
-					content.append("t=0 0\r\n");
-					content.append("m=video "+ sendRtpItem.getLocalPort()+" RTP/AVP 96\r\n");
-					content.append("a=sendonly\r\n");
-					content.append("a=rtpmap:96 PS/90000\r\n");
-					content.append("y="+ ssrc + "\r\n");
-					content.append("f=\r\n");
+					// 閫氱煡涓嬬骇鎺ㄦ祦锛�
+					PlayResult playResult = playService.play(device.getDeviceId(), channelId, (responseJSON)->{
+						// 鏀跺埌鎺ㄦ祦锛� 鍥炲200OK, 绛夊緟ack
+						if (sendRtpItem == null) return;
+						sendRtpItem.setStatus(1);
+						redisCatchStorage.updateSendRTPSever(sendRtpItem);
+						// TODO 娣诲姞瀵箃cp鐨勬敮鎸�
+						MediaServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
+						StringBuffer content = new StringBuffer(200);
+						content.append("v=0\r\n");
+						content.append("o="+"00000"+" 0 0 IN IP4 "+mediaInfo.getWanIp()+"\r\n");
+						content.append("s=Play\r\n");
+						content.append("c=IN IP4 "+mediaInfo.getWanIp()+"\r\n");
+						content.append("t=0 0\r\n");
+						content.append("m=video "+ sendRtpItem.getLocalPort()+" RTP/AVP 96\r\n");
+						content.append("a=sendonly\r\n");
+						content.append("a=rtpmap:96 PS/90000\r\n");
+						content.append("y="+ ssrc + "\r\n");
+						content.append("f=\r\n");
 
-					try {
-						responseAck(evt, content.toString());
-					} catch (SipException e) {
-						e.printStackTrace();
-					} catch (InvalidArgumentException e) {
-						e.printStackTrace();
-					} catch (ParseException e) {
-						e.printStackTrace();
+						try {
+							responseAck(evt, content.toString());
+						} catch (SipException e) {
+							e.printStackTrace();
+						} catch (InvalidArgumentException e) {
+							e.printStackTrace();
+						} catch (ParseException e) {
+							e.printStackTrace();
+						}
+					} ,(event -> {
+						// 鏈煡閿欒銆傜洿鎺ヨ浆鍙戣澶囩偣鎾殑閿欒
+						Response response = null;
+						try {
+							response = getMessageFactory().createResponse(event.getResponse().getStatusCode(), evt.getRequest());
+							getServerTransaction(evt).sendResponse(response);
+						} catch (ParseException | SipException | InvalidArgumentException e) {
+							e.printStackTrace();
+						}
+					}));
+					if (logger.isDebugEnabled()) {
+						logger.debug(playResult.getResult().toString());
 					}
-				},(event -> {
-					// 鏈煡閿欒銆傜洿鎺ヨ浆鍙戣澶囩偣鎾殑閿欒
-					Response response = null;
-					try {
-						response = getMessageFactory().createResponse(event.getResponse().getStatusCode(), evt.getRequest());
-						getServerTransaction(evt).sendResponse(response);
-					} catch (ParseException | SipException | InvalidArgumentException e) {
-						e.printStackTrace();
+
+				}else if (gbStream != null) {
+					SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(addressStr, port, ssrc, requesterId,
+							gbStream.getApp(), gbStream.getStream(), channelId,
+							mediaTransmissionTCP);
+
+					if (tcpActive != null) {
+						sendRtpItem.setTcpActive(tcpActive);
 					}
-				}));
-				if (logger.isDebugEnabled()) {
-					logger.debug(playResult.getResult().toString());
+					if (sendRtpItem == null) {
+						logger.warn("鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�");
+						responseAck(evt, Response.BUSY_HERE);
+						return;
+					}
+
+					// 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶�
+					redisCatchStorage.updateSendRTPSever(sendRtpItem);
+
+					// 妫�娴嬬洿鎾祦鏄惁鍦ㄧ嚎
+					Boolean streamReady = zlmrtpServerFactory.isStreamReady(gbStream.getApp(), gbStream.getStream());
+					if (streamReady) {
+						sendRtpItem.setStatus(1);
+						redisCatchStorage.updateSendRTPSever(sendRtpItem);
+						// TODO 娣诲姞瀵箃cp鐨勬敮鎸�
+						MediaServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
+						StringBuffer content = new StringBuffer(200);
+						content.append("v=0\r\n");
+						content.append("o="+"00000"+" 0 0 IN IP4 "+mediaInfo.getWanIp()+"\r\n");
+						content.append("s=Play\r\n");
+						content.append("c=IN IP4 "+mediaInfo.getWanIp()+"\r\n");
+						content.append("t=0 0\r\n");
+						content.append("m=video "+ sendRtpItem.getLocalPort()+" RTP/AVP 96\r\n");
+						content.append("a=sendonly\r\n");
+						content.append("a=rtpmap:96 PS/90000\r\n");
+						content.append("y="+ ssrc + "\r\n");
+						content.append("f=\r\n");
+
+						try {
+							responseAck(evt, content.toString());
+						} catch (SipException e) {
+							e.printStackTrace();
+						} catch (InvalidArgumentException e) {
+							e.printStackTrace();
+						} catch (ParseException e) {
+							e.printStackTrace();
+						}
+					}
 				}
+
 			} else {
 				// 闈炰笂绾у钩鍙拌姹傦紝鏌ヨ鏄惁璁惧璇锋眰锛堥�氬父涓烘帴鏀惰闊冲箍鎾殑璁惧锛�
 				Device device = storager.queryVideoDevice(requesterId);
@@ -298,6 +354,7 @@
 		}
 	}
 
+
 	/***
 	 * 鍥炲鐘舵�佺爜
 	 * 100 trying
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
index 5a24202..8176f45 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
@@ -529,13 +529,44 @@
 					String sn = snElement.getText();
 					// 鍑嗗鍥炲閫氶亾淇℃伅
 					List<ChannelReduce> channelReduces = storager.queryChannelListInParentPlatform(parentPlatform.getServerGBId());
+					// 鏌ヨ鍏宠仈鐨勭洿鎾�氶亾
+					List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(parentPlatform.getServerGBId());
+					int size = channelReduces.size() + gbStreams.size();
+					// 鍥炲绾ц仈鐨勯�氶亾
 					if (channelReduces.size() > 0) {
 						for (ChannelReduce channelReduce : channelReduces) {
 							DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId());
-							cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), channelReduces.size());
+							cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
 						}
 					}
+					// 鍥炲鐩存挱鐨勯�氶亾
+					if (gbStreams.size() > 0) {
+						for (GbStream gbStream : gbStreams) {
+							DeviceChannel deviceChannel = new DeviceChannel();
+							deviceChannel.setChannelId(gbStream.getGbId());
+							deviceChannel.setName(gbStream.getName());
+							deviceChannel.setLongitude(gbStream.getLongitude());
+							deviceChannel.setLatitude(gbStream.getLatitude());
+							deviceChannel.setDeviceId(parentPlatform.getDeviceGBId());
+							deviceChannel.setManufacture("wvp-pro");
+							deviceChannel.setStatus(1);
+//							deviceChannel.setParentId(parentPlatform.getDeviceGBId());
+							deviceChannel.setRegisterWay(1);
+							deviceChannel.setCivilCode(cmder.getSipConfig().getSipDomain());
+							deviceChannel.setModel("live");
+							deviceChannel.setOwner("wvp-pro");
+//							deviceChannel.setAddress("test");
+							deviceChannel.setParental(0);
+							deviceChannel.setSecrecy("0");
+							deviceChannel.setSecrecy("0");
 
+							cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
+						}
+					}
+					if (size == 0) {
+						// 鍥炲鏃犻�氶亾
+						cmderFroPlatform.catalogQuery(null, parentPlatform, sn, fromHeader.getTag(), size);
+					}
 				}
 
 
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 1f1693d..02fb742 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
@@ -96,7 +96,7 @@
     }
 
     /**
-     * 鍒涘缓涓�涓帹娴�
+     * 鍒涘缓涓�涓浗鏍囨帹娴�
      * @param ip 鎺ㄦ祦ip
      * @param port 鎺ㄦ祦绔彛
      * @param ssrc 鎺ㄦ祦鍞竴鏍囪瘑
@@ -120,6 +120,39 @@
         sendRtpItem.setSsrc(ssrc);
         sendRtpItem.setPlatformId(platformId);
         sendRtpItem.setDeviceId(deviceId);
+        sendRtpItem.setChannelId(channelId);
+        sendRtpItem.setTcp(tcp);
+        sendRtpItem.setApp("rtp");
+        sendRtpItem.setLocalPort(localPort);
+        return sendRtpItem;
+    }
+
+    /**
+     * 鍒涘缓涓�涓洿鎾帹娴�
+     * @param ip 鎺ㄦ祦ip
+     * @param port 鎺ㄦ祦绔彛
+     * @param ssrc 鎺ㄦ祦鍞竴鏍囪瘑
+     * @param platformId 骞冲彴id
+     * @param channelId 閫氶亾id
+     * @param tcp 鏄惁涓簍cp
+     * @return SendRtpItem
+     */
+    public SendRtpItem createSendRtpItem(String ip, int port, String ssrc, String platformId, String app, String stream, String channelId, boolean tcp){
+        String playSsrc = SsrcUtil.getPlaySsrc();
+        int localPort = createRTPServer(SsrcUtil.getPlaySsrc());
+        if (localPort != -1) {
+            closeRTPServer(playSsrc);
+        }else {
+            logger.error("娌℃湁鍙敤鐨勭鍙�");
+            return null;
+        }
+        SendRtpItem sendRtpItem = new SendRtpItem();
+        sendRtpItem.setIp(ip);
+        sendRtpItem.setPort(port);
+        sendRtpItem.setSsrc(ssrc);
+        sendRtpItem.setApp(app);
+        sendRtpItem.setStreamId(stream);
+        sendRtpItem.setPlatformId(platformId);
         sendRtpItem.setChannelId(channelId);
         sendRtpItem.setTcp(tcp);
         sendRtpItem.setLocalPort(localPort);
@@ -153,12 +186,20 @@
     }
 
     /**
+     * 鏌ヨ寰呰浆鎺ㄧ殑娴佹槸鍚﹀氨缁�
+     */
+    public Boolean isStreamReady(String app, String streamId) {
+        JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(app, "rtmp", streamId);
+        return (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online"));
+    }
+
+    /**
      * 鏌ヨ杞帹鐨勬祦鏄惁鏈夊叾瀹冭鐪嬭��
      * @param streamId
      * @return
      */
-    public int totalReaderCount(String streamId) {
-        JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo("rtp", "rtmp", streamId);
+    public int totalReaderCount(String app, String streamId) {
+        JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(app, "rtmp", streamId);
         return mediaInfo.getInteger("totalReaderCount");
     }
 
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 15fa957..1340a68 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,7 +4,7 @@
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.genersoft.iot.vmp.conf.MediaServerConfig;
-import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyDto;
+import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 //import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
@@ -165,8 +165,8 @@
         // 鏇存柊娴佸垪琛�
         zlmMediaListManager.updateMediaList();
         // 鎭㈠娴佷唬鐞�
-        List<StreamProxyDto> streamProxyListForEnable = storager.getStreamProxyListForEnable(true);
-        for (StreamProxyDto streamProxyDto : streamProxyListForEnable) {
+        List<StreamProxyItem> streamProxyListForEnable = storager.getStreamProxyListForEnable(true);
+        for (StreamProxyItem streamProxyDto : streamProxyListForEnable) {
             logger.info("鎭㈠娴佷唬鐞嗭紝" + streamProxyDto.getApp() + "/" + streamProxyDto.getStream());
             streamProxyService.addStreamProxyToZlm(streamProxyDto);
         }
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyDto.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyItem.java
similarity index 95%
rename from src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyDto.java
rename to src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyItem.java
index 8f03602..f04e756 100644
--- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyDto.java
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyItem.java
@@ -1,6 +1,9 @@
 package com.genersoft.iot.vmp.media.zlm.dto;
 
-public class StreamProxyDto {
+import com.genersoft.iot.vmp.gb28181.bean.GbStream;
+
+public class StreamProxyItem extends GbStream {
+
     private String type;
     private String app;
     private String stream;
@@ -109,4 +112,6 @@
     public void setEnable_mp4(boolean enable_mp4) {
         this.enable_mp4 = enable_mp4;
     }
+
+
 }
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 7656898..e8f3240 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java
@@ -2,12 +2,9 @@
 
 import java.util.List;
 
-import com.genersoft.iot.vmp.gb28181.bean.Device;
-import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
-import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
-import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyDto;
+import com.genersoft.iot.vmp.gb28181.bean.*;
+import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
 import com.genersoft.iot.vmp.vmanager.platform.bean.ChannelReduce;
-import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
 import com.github.pagehelper.PageInfo;
 
 /**    
@@ -238,7 +235,7 @@
 
 	/**
 	 * 娣诲姞Mobile Position璁惧绉诲姩浣嶇疆
-	 * @param MobilePosition
+	 * @param mobilePosition
 	 * @return
 	 */
 	public boolean insertMobilePosition(MobilePosition mobilePosition);
@@ -268,14 +265,14 @@
 	 * @param streamProxyDto
 	 * @return
 	 */
-	public int addStreamProxy(StreamProxyDto streamProxyDto);
+	public boolean addStreamProxy(StreamProxyItem streamProxyDto);
 
 	/**
 	 * 鏇存柊浠g悊娴�
 	 * @param streamProxyDto
 	 * @return
 	 */
-	public int updateStreamProxy(StreamProxyDto streamProxyDto);
+	public boolean updateStreamProxy(StreamProxyItem streamProxyDto);
 
 	/**
 	 * 绉婚櫎浠g悊娴�
@@ -290,7 +287,7 @@
 	 * @param enable
 	 * @return
 	 */
-	public List<StreamProxyDto> getStreamProxyListForEnable(boolean enable);
+	public List<StreamProxyItem> getStreamProxyListForEnable(boolean enable);
 
 	/**
 	 * 鎸夌収鏄痑pp鍜宻tream鑾峰彇浠g悊娴�
@@ -298,7 +295,7 @@
 	 * @param stream
 	 * @return
 	 */
-	public StreamProxyDto queryStreamProxy(String app, String stream);
+	public StreamProxyItem queryStreamProxy(String app, String stream);
 
 	/**
 	 * 鑾峰彇浠g悊娴�
@@ -306,5 +303,20 @@
 	 * @param count
 	 * @return
 	 */
-	PageInfo<StreamProxyDto> queryStreamProxyList(Integer page, Integer count);
+	PageInfo<StreamProxyItem> queryStreamProxyList(Integer page, Integer count);
+
+	/**
+	 * 鏍规嵁鍥芥爣ID鑾峰彇骞冲彴鍏宠仈鐨勭洿鎾祦
+	 * @param platformId
+	 * @param channelId
+	 * @return
+	 */
+	GbStream queryStreamInParentPlatform(String platformId, String channelId);
+
+	/**
+	 * 鑾峰彇骞冲彴鍏宠仈鐨勭洿鎾祦
+	 * @param platformId
+	 * @return
+	 */
+	List<GbStream> queryGbStreamListInPlatform(String platformId);
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java
new file mode 100644
index 0000000..2b83a4a
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java
@@ -0,0 +1,49 @@
+package com.genersoft.iot.vmp.storager.dao;
+
+import com.genersoft.iot.vmp.gb28181.bean.GbStream;
+import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
+import org.apache.ibatis.annotations.*;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Mapper
+@Repository
+public interface GbStreamMapper {
+
+    @Insert("INSERT INTO gb_stream (app, stream, gbId, name, " +
+            "longitude, latitude, streamType) VALUES" +
+            "('${app}', '${stream}', '${gbId}', '${name}', " +
+            "'${longitude}', '${latitude}', '${streamType}')")
+    int add(GbStream gbStream);
+
+    @Update("UPDATE gb_stream " +
+            "SET app=#{app}," +
+            "stream=#{stream}," +
+            "gbId=#{gbId}," +
+            "name=#{name}," +
+            "streamType=#{streamType}," +
+            "longitude=#{longitude}, " +
+            "latitude=#{latitude}, " +
+            "WHERE app=#{app} AND stream=#{stream} AND gbId=#{gbId}")
+    int update(GbStream gbStream);
+
+    @Delete("DELETE FROM gb_stream WHERE app=#{app} AND stream=#{stream}")
+    int del(String app, String stream);
+
+    @Select("SELECT gs.*, pgs.platformId FROM gb_stream gs LEFT JOIN  platform_gb_stream pgs ON gs.app = pgs.app AND gs.stream = pgs.stream")
+    List<GbStream> selectAll();
+
+    @Select("SELECT * FROM gb_stream WHERE app=#{app} AND stream=#{stream}")
+    StreamProxyItem selectOne(String app, String stream);
+
+    @Select("SELECT gs.*, pgs.platformId FROM gb_stream gs " +
+            "LEFT JOIN platform_gb_stream pgs ON gs.app = pgs.app AND gs.stream = pgs.stream " +
+            "WHERE gs.gbId = '${gbId}' AND pgs.platformId = '${platformId}'")
+    GbStream queryStreamInPlatform(String platformId, String gbId);
+
+    @Select("SELECT gs.*, pgs.platformId FROM gb_stream gs " +
+            "LEFT JOIN platform_gb_stream pgs ON gs.app = pgs.app AND gs.stream = pgs.stream " +
+            "WHERE pgs.platformId = '${platformId}'")
+    List<GbStream> queryGbStreamListInPlatform(String platformId);
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/PlarfotmGbStreamMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/PlarfotmGbStreamMapper.java
new file mode 100644
index 0000000..1172aeb
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/PlarfotmGbStreamMapper.java
@@ -0,0 +1,28 @@
+package com.genersoft.iot.vmp.storager.dao;
+
+import com.genersoft.iot.vmp.gb28181.bean.GbStream;
+import com.genersoft.iot.vmp.gb28181.bean.PlatformGbStream;
+import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
+import org.apache.ibatis.annotations.*;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+
+@Mapper
+@Repository
+public interface PlarfotmGbStreamMapper {
+
+    @Insert("INSERT INTO platform_gb_stream (app, stream, platformId) VALUES" +
+            "('${app}', '${stream}', '${platformId}')")
+    int add(PlatformGbStream platformGbStream);
+
+    @Delete("DELETE FROM platform_gb_stream WHERE app=#{app} AND stream=#{stream}")
+    int delByAppAndStream(String app, String stream);
+
+    @Delete("DELETE FROM platform_gb_stream WHERE app=#{app} AND stream=#{stream}")
+    int delByPlatformId(String platformId);
+
+    @Select("SELECT * FROM platform_gb_stream WHERE app=#{app} AND stream=#{stream} AND platformId=#{platformId}")
+    StreamProxyItem selectOne(String app, String stream, String platformId);
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/PatformChannelMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformChannelMapper.java
similarity index 98%
rename from src/main/java/com/genersoft/iot/vmp/storager/dao/PatformChannelMapper.java
rename to src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformChannelMapper.java
index 50eb3e3..a88f266 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/dao/PatformChannelMapper.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformChannelMapper.java
@@ -13,7 +13,7 @@
 
 @Mapper
 @Repository
-public interface PatformChannelMapper {
+public interface PlatformChannelMapper {
 
     /**
      * 鏌ヨ鍒楄〃閲屽凡缁忓叧鑱旂殑
diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java
index 414125b..3f53c36 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java
@@ -1,6 +1,6 @@
 package com.genersoft.iot.vmp.storager.dao;
 
-import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyDto;
+import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
 import org.apache.ibatis.annotations.*;
 import org.springframework.stereotype.Repository;
 
@@ -14,7 +14,7 @@
             "timeout_ms, ffmpeg_cmd_key, rtp_type, enable_hls, enable_mp4, enable) VALUES" +
             "('${type}','${app}', '${stream}', '${url}', '${src_url}', '${dst_url}', " +
             "'${timeout_ms}', '${ffmpeg_cmd_key}', '${rtp_type}', ${enable_hls}, ${enable_mp4}, ${enable} )")
-    int add(StreamProxyDto streamProxyDto);
+    int add(StreamProxyItem streamProxyDto);
 
     @Update("UPDATE stream_proxy " +
             "SET type=#{type}, " +
@@ -30,17 +30,17 @@
             "enable=#{enable}, " +
             "enable_mp4=#{enable_mp4} " +
             "WHERE app=#{app} AND stream=#{stream}")
-    int update(StreamProxyDto streamProxyDto);
+    int update(StreamProxyItem streamProxyDto);
 
     @Delete("DELETE FROM stream_proxy WHERE app=#{app} AND stream=#{stream}")
     int del(String app, String stream);
 
-    @Select("SELECT * FROM stream_proxy")
-    List<StreamProxyDto> selectAll();
+    @Select("SELECT st.*, pgs.gbId, pgs.name, pgs.longitude, pgs.latitude FROM stream_proxy st LEFT JOIN gb_stream pgs on st.app = pgs.app AND st.stream = pgs.stream")
+    List<StreamProxyItem> selectAll();
 
-    @Select("SELECT * FROM stream_proxy WHERE enable=${enable}")
-    List<StreamProxyDto> selectForEnable(boolean enable);
+    @Select("SELECT st.*, pgs.gbId, pgs.name, pgs.longitude, pgs.latitude FROM stream_proxy st LEFT JOIN gb_stream pgs on st.app = pgs.app AND st.stream = pgs.stream WHERE st.enable=${enable}")
+    List<StreamProxyItem> selectForEnable(boolean enable);
 
-    @Select("SELECT * FROM stream_proxy WHERE app=#{app} AND stream=#{stream}")
-    StreamProxyDto selectOne(String app, String stream);
+    @Select("SELECT st.*, pgs.gbId, pgs.name, pgs.longitude, pgs.latitude FROM stream_proxy st LEFT JOIN gb_stream pgs on st.app = pgs.app AND st.stream = pgs.stream WHERE st.app=#{app} AND st.stream=#{stream}")
+    StreamProxyItem selectOne(String app, String stream);
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java
index 071bf68..b2756e2 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java
@@ -2,21 +2,20 @@
 
 import java.util.*;
 
-import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
-import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
-import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
-import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyDto;
+import com.genersoft.iot.vmp.gb28181.bean.*;
+import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
-import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
 import com.genersoft.iot.vmp.storager.dao.*;
 import com.genersoft.iot.vmp.vmanager.platform.bean.ChannelReduce;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
 import org.springframework.stereotype.Component;
 
-import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionStatus;
 import org.springframework.transaction.annotation.Transactional;
 
 /**    
@@ -27,6 +26,11 @@
 @SuppressWarnings("rawtypes")
 @Component
 public class VideoManagerStoragerImpl implements IVideoManagerStorager {
+	@Autowired
+	DataSourceTransactionManager dataSourceTransactionManager;
+
+	@Autowired
+	TransactionDefinition transactionDefinition;
 
 	@Autowired
     private DeviceMapper deviceMapper;
@@ -44,12 +48,13 @@
     private IRedisCatchStorage redisCatchStorage;
 
 	@Autowired
-    private PatformChannelMapper patformChannelMapper;
+    private PlatformChannelMapper platformChannelMapper;
 
 	@Autowired
     private StreamProxyMapper streamProxyMapper;
 
-
+	@Autowired
+    private GbStreamMapper gbStreamMapper;
 
 
 	/**
@@ -283,7 +288,7 @@
 	public boolean deleteParentPlatform(ParentPlatform parentPlatform) {
 		int result = platformMapper.delParentPlatform(parentPlatform);
 		// 鍒犻櫎鍏宠仈鐨勯�氶亾
-		patformChannelMapper.cleanChannelForGB(parentPlatform.getServerGBId());
+		platformChannelMapper.cleanChannelForGB(parentPlatform.getServerGBId());
 		return result > 0;
 	}
 
@@ -333,7 +338,7 @@
 		}
 		List<String> deviceAndChannelList = new ArrayList<>(deviceAndChannels.keySet());
 		// 鏌ヨ褰撳墠宸茬粡瀛樺湪鐨�
-		List<String> relatedPlatformchannels = patformChannelMapper.findChannelRelatedPlatform(platformId, deviceAndChannelList);
+		List<String> relatedPlatformchannels = platformChannelMapper.findChannelRelatedPlatform(platformId, deviceAndChannelList);
 		if (relatedPlatformchannels != null) {
 			deviceAndChannelList.removeAll(relatedPlatformchannels);
 		}
@@ -344,7 +349,7 @@
 		// 瀵瑰墿涓嬬殑鏁版嵁杩涜瀛樺偍
 		int result = 0;
 		if (channelReducesToAdd.size() > 0) {
-			result = patformChannelMapper.addChannels(platformId, channelReducesToAdd);
+			result = platformChannelMapper.addChannels(platformId, channelReducesToAdd);
 		}
 
 		return result;
@@ -354,20 +359,20 @@
 	@Override
 	public int delChannelForGB(String platformId, List<ChannelReduce> channelReduces) {
 
-		int result = patformChannelMapper.delChannelForGB(platformId, channelReduces);
+		int result = platformChannelMapper.delChannelForGB(platformId, channelReduces);
 
 		return result;
 	}
 
 	@Override
 	public DeviceChannel queryChannelInParentPlatform(String platformId, String channelId) {
-		DeviceChannel channel = patformChannelMapper.queryChannelInParentPlatform(platformId, channelId);
+		DeviceChannel channel = platformChannelMapper.queryChannelInParentPlatform(platformId, channelId);
 		return channel;
 	}
 
 	@Override
 	public Device queryVideoDeviceByPlatformIdAndChannelId(String platformId, String channelId) {
-		Device device = patformChannelMapper.queryVideoDeviceByPlatformIdAndChannelId(platformId, channelId);
+		Device device = platformChannelMapper.queryVideoDeviceByPlatformIdAndChannelId(platformId, channelId);
 		return device;
 	}
 
@@ -390,27 +395,54 @@
 
 	/**
 	 * 鏂板浠g悊娴�
-	 * @param streamProxyDto
+	 * @param streamProxyItem
 	 * @return
 	 */
 	@Override
-	public int addStreamProxy(StreamProxyDto streamProxyDto) {
-		return streamProxyMapper.add(streamProxyDto);
+	public boolean addStreamProxy(StreamProxyItem streamProxyItem) {
+		TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
+		boolean result = false;
+		streamProxyItem.setStreamType("proxy");
+		try {
+			if (gbStreamMapper.add(streamProxyItem)<0 || streamProxyMapper.add(streamProxyItem) < 0) {
+				//浜嬪姟鍥炴粴
+				dataSourceTransactionManager.rollback(transactionStatus);
+			}
+			result = true;
+			dataSourceTransactionManager.commit(transactionStatus);     //鎵嬪姩鎻愪氦
+		}catch (Exception e) {
+			dataSourceTransactionManager.rollback(transactionStatus);
+		}
+		return result;
 	}
 
 	/**
 	 * 鏇存柊浠g悊娴�
-	 * @param streamProxyDto
+	 * @param streamProxyItem
 	 * @return
 	 */
 	@Override
-	public int updateStreamProxy(StreamProxyDto streamProxyDto) {
-		return streamProxyMapper.update(streamProxyDto);
+	public boolean updateStreamProxy(StreamProxyItem streamProxyItem) {
+		TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
+		boolean result = false;
+		streamProxyItem.setStreamType("proxy");
+		try {
+			if (gbStreamMapper.update(streamProxyItem)<0 || streamProxyMapper.update(streamProxyItem) < 0) {
+				//浜嬪姟鍥炴粴
+				dataSourceTransactionManager.rollback(transactionStatus);
+			}
+			dataSourceTransactionManager.commit(transactionStatus);     //鎵嬪姩鎻愪氦
+			result = true;
+		}catch (Exception e) {
+			dataSourceTransactionManager.rollback(transactionStatus);
+		}
+		return result;
 	}
 
 	/**
 	 * 绉婚櫎浠g悊娴�
-	 * @param id
+	 * @param app
+	 * @param stream
 	 * @return
 	 */
 	@Override
@@ -424,7 +456,7 @@
 	 * @return
 	 */
 	@Override
-	public List<StreamProxyDto> getStreamProxyListForEnable(boolean enable) {
+	public List<StreamProxyItem> getStreamProxyListForEnable(boolean enable) {
 		return streamProxyMapper.selectForEnable(enable);
 	}
 
@@ -435,12 +467,32 @@
 	 * @return
 	 */
 	@Override
-	public PageInfo<StreamProxyDto> queryStreamProxyList(Integer page, Integer count) {
+	public PageInfo<StreamProxyItem> queryStreamProxyList(Integer page, Integer count) {
 		PageHelper.startPage(page, count);
-		List<StreamProxyDto> all = streamProxyMapper.selectAll();
+		List<StreamProxyItem> all = streamProxyMapper.selectAll();
 		return new PageInfo<>(all);
 	}
 
+	/**
+	 * 鏍规嵁鍥芥爣ID鑾峰彇骞冲彴鍏宠仈鐨勭洿鎾祦
+	 * @param platformId
+	 * @param gbId
+	 * @return
+	 */
+	@Override
+	public GbStream queryStreamInParentPlatform(String platformId, String gbId) {
+		return gbStreamMapper.queryStreamInPlatform(platformId, gbId);
+	}
+
+	/**
+	 * 鑾峰彇骞冲彴鍏宠仈鐨勭洿鎾祦
+	 * @param platformId
+	 * @return
+	 */
+	@Override
+	public List<GbStream> queryGbStreamListInPlatform(String platformId) {
+		return gbStreamMapper.queryGbStreamListInPlatform(platformId);
+	}
 
 	/**
 	 * 鎸夌収鏄痑pp鍜宻tream鑾峰彇浠g悊娴�
@@ -449,7 +501,7 @@
 	 * @return
 	 */
 	@Override
-	public StreamProxyDto queryStreamProxy(String app, String stream){
+	public StreamProxyItem queryStreamProxy(String app, String stream){
 		return streamProxyMapper.selectOne(app, stream);
 	}
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gbStream/GbStreamController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gbStream/GbStreamController.java
new file mode 100644
index 0000000..d6afb09
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gbStream/GbStreamController.java
@@ -0,0 +1,65 @@
+package com.genersoft.iot.vmp.vmanager.gbStream;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.genersoft.iot.vmp.gb28181.bean.GbStream;
+import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
+import com.genersoft.iot.vmp.vmanager.gbStream.bean.GbStreamParam;
+import com.genersoft.iot.vmp.vmanager.platform.bean.UpdateChannelParam;
+import com.genersoft.iot.vmp.vmanager.service.IGbStreamService;
+import com.github.pagehelper.PageInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@CrossOrigin
+@RestController
+@RequestMapping("/api/gbStream")
+public class GbStreamController {
+
+    private final static Logger logger = LoggerFactory.getLogger(GbStreamController.class);
+
+    @Autowired
+    private IGbStreamService gbStreamService;
+
+    @Autowired
+    private IVideoManagerStorager storager;
+
+
+    @RequestMapping(value = "/list")
+    @ResponseBody
+    public PageInfo<GbStream> list(@RequestParam(required = false)Integer page,
+                                   @RequestParam(required = false)Integer count){
+
+        return gbStreamService.getAll(page, count);
+    }
+
+
+    @RequestMapping(value = "/del")
+    @ResponseBody
+    public Object del(@RequestBody GbStreamParam gbStreamParam){
+        System.out.println(2222);
+        System.out.println(gbStreamParam.getGbStreams().size());
+        if (gbStreamService.delPlatformInfo(gbStreamParam.getGbStreams())) {
+            return "success";
+        }else {
+            return "fail";
+        }
+
+    }
+
+    @RequestMapping(value = "/add")
+    @ResponseBody
+    public Object add(@RequestBody GbStreamParam gbStreamParam){
+        System.out.println(3333);
+        System.out.println(gbStreamParam.getGbStreams().size());
+        if (gbStreamService.addPlatformInfo(gbStreamParam.getGbStreams(), gbStreamParam.getPlatformId())) {
+            return "success";
+        }else {
+            return "fail";
+        }
+    }
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gbStream/bean/GbStreamParam.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gbStream/bean/GbStreamParam.java
new file mode 100644
index 0000000..2181cc8
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gbStream/bean/GbStreamParam.java
@@ -0,0 +1,28 @@
+package com.genersoft.iot.vmp.vmanager.gbStream.bean;
+
+import com.genersoft.iot.vmp.gb28181.bean.GbStream;
+
+import java.util.List;
+
+public class GbStreamParam {
+
+    private String platformId;
+
+    private List<GbStream> gbStreams;
+
+    public String getPlatformId() {
+        return platformId;
+    }
+
+    public void setPlatformId(String platformId) {
+        this.platformId = platformId;
+    }
+
+    public List<GbStream> getGbStreams() {
+        return gbStreams;
+    }
+
+    public void setGbStreams(List<GbStream> gbStreams) {
+        this.gbStreams = gbStreams;
+    }
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/media/MediaController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/media/MediaController.java
index 115e840..0710f9b 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/media/MediaController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/media/MediaController.java
@@ -46,7 +46,4 @@
         return mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream);
     }
 
-
-
-
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/platformGbStream/PlatformGbStreamController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/platformGbStream/PlatformGbStreamController.java
new file mode 100644
index 0000000..f2db340
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/platformGbStream/PlatformGbStreamController.java
@@ -0,0 +1,35 @@
+package com.genersoft.iot.vmp.vmanager.platformGbStream;
+
+import com.genersoft.iot.vmp.gb28181.bean.GbStream;
+import com.genersoft.iot.vmp.gb28181.bean.PlatformGbStream;
+import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
+import com.genersoft.iot.vmp.vmanager.service.IGbStreamService;
+import com.github.pagehelper.PageInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+@CrossOrigin
+@RestController
+@RequestMapping("/api")
+public class PlatformGbStreamController {
+
+    private final static Logger logger = LoggerFactory.getLogger(PlatformGbStreamController.class);
+
+    @Autowired
+    private IGbStreamService gbStreamService;
+
+    @Autowired
+    private IVideoManagerStorager storager;
+
+    @RequestMapping(value = "/list")
+    @ResponseBody
+    public PageInfo<GbStream> list(@RequestParam(required = false)Integer page,
+                                   @RequestParam(required = false)Integer count){
+
+        return gbStreamService.getAll(page, count);
+    }
+
+
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java
index 67045b4..c4bee6d 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java
@@ -163,20 +163,7 @@
 				JSONObject data = jsonObject.getJSONObject("data");
 				if (data != null) {
 				   	result.put("key", data.getString("key"));
-//					StreamInfo streamInfoResult = new StreamInfo();
-//					streamInfoResult.setRtmp(dstUrl);
-//					streamInfoResult.setRtsp(String.format("rtsp://%s:%s/convert/%s", mediaInfo.getWanIp(), mediaInfo.getRtspPort(), streamId));
-//					streamInfoResult.setStreamId(streamId);
-//					streamInfoResult.setFlv(String.format("http://%s:%s/convert/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));
-//					streamInfoResult.setWs_flv(String.format("ws://%s:%s/convert/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));
-//					streamInfoResult.setHls(String.format("http://%s:%s/convert/%s/hls.m3u8", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));
-//					streamInfoResult.setWs_hls(String.format("ws://%s:%s/convert/%s/hls.m3u8", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));
-//					streamInfoResult.setFmp4(String.format("http://%s:%s/convert/%s.live.mp4", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));
-//					streamInfoResult.setWs_fmp4(String.format("ws://%s:%s/convert/%s.live.mp4", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));
-//					streamInfoResult.setTs(String.format("http://%s:%s/convert/%s.live.ts", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));
-//					streamInfoResult.setWs_ts(String.format("ws://%s:%s/convert/%s.live.ts", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));
 					StreamInfo streamInfoResult = mediaService.getStreamInfoByAppAndStream("convert", streamId);
-					streamInfoResult.setStreamId(streamId);
 					result.put("data", streamInfoResult);
 				}
 			}else {
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/service/IGbStreamService.java b/src/main/java/com/genersoft/iot/vmp/vmanager/service/IGbStreamService.java
new file mode 100644
index 0000000..877ec2a
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/service/IGbStreamService.java
@@ -0,0 +1,41 @@
+package com.genersoft.iot.vmp.vmanager.service;
+
+import com.genersoft.iot.vmp.gb28181.bean.GbStream;
+import com.genersoft.iot.vmp.gb28181.bean.PlatformGbStream;
+import com.github.pagehelper.PageInfo;
+
+import java.util.List;
+
+/**
+ * 绾ц仈鍥芥爣骞冲彴鍏宠仈娴佷笟鍔℃帴鍙�
+ */
+public interface IGbStreamService {
+
+    /**
+     * 鍒嗛〉鑾峰彇鎵�鏈�
+     * @param page
+     * @param count
+     * @return
+     */
+    PageInfo<GbStream> getAll(Integer page, Integer count);
+
+
+    /**
+     * 绉婚櫎
+     * @param app
+     * @param stream
+     */
+    void del(String app, String stream);
+
+    /**
+     * 淇濆瓨鍥芥爣鍏宠仈
+     * @param gbStreams
+     */
+    boolean addPlatformInfo(List<GbStream> gbStreams, String platformId);
+
+    /**
+     * 绉婚櫎鍥芥爣鍏宠仈
+     * @param gbStreams
+     */
+    boolean delPlatformInfo(List<GbStream> gbStreams);
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/service/IStreamProxyService.java b/src/main/java/com/genersoft/iot/vmp/vmanager/service/IStreamProxyService.java
index 4a93cd2..49d1e8a 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/service/IStreamProxyService.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/service/IStreamProxyService.java
@@ -1,8 +1,7 @@
 package com.genersoft.iot.vmp.vmanager.service;
 
 import com.alibaba.fastjson.JSONObject;
-import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyDto;
-import com.genersoft.iot.vmp.vmanager.streamProxy.StreamProxyController;
+import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
 import com.github.pagehelper.PageInfo;
 
 public interface IStreamProxyService {
@@ -11,21 +10,21 @@
      * 淇濆瓨瑙嗛浠g悊
      * @param param
      */
-    void save(StreamProxyDto param);
+    void save(StreamProxyItem param);
 
     /**
      * 娣诲姞瑙嗛浠g悊鍒皕lm
      * @param param
      * @return
      */
-    JSONObject addStreamProxyToZlm(StreamProxyDto param);
+    JSONObject addStreamProxyToZlm(StreamProxyItem param);
 
     /**
      * 浠巣lm绉婚櫎瑙嗛浠g悊
      * @param param
      * @return
      */
-    JSONObject removeStreamProxyFromZlm(StreamProxyDto param);
+    JSONObject removeStreamProxyFromZlm(StreamProxyItem param);
 
     /**
      * 鍒嗛〉鏌ヨ
@@ -33,7 +32,7 @@
      * @param count
      * @return
      */
-    PageInfo<StreamProxyDto> getAll(Integer page, Integer count);
+    PageInfo<StreamProxyItem> getAll(Integer page, Integer count);
 
     /**
      * 鍒犻櫎瑙嗛浠g悊
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/GbStreamServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/GbStreamServiceImpl.java
new file mode 100644
index 0000000..b8caacd
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/GbStreamServiceImpl.java
@@ -0,0 +1,89 @@
+package com.genersoft.iot.vmp.vmanager.service.impl;
+
+import com.genersoft.iot.vmp.gb28181.bean.GbStream;
+import com.genersoft.iot.vmp.gb28181.bean.PlatformGbStream;
+import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
+import com.genersoft.iot.vmp.storager.dao.GbStreamMapper;
+import com.genersoft.iot.vmp.storager.dao.PlarfotmGbStreamMapper;
+import com.genersoft.iot.vmp.vmanager.platform.PlatformController;
+import com.genersoft.iot.vmp.vmanager.service.IGbStreamService;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionStatus;
+
+import java.util.List;
+
+@Service
+public class GbStreamServiceImpl implements IGbStreamService {
+
+    private final static Logger logger = LoggerFactory.getLogger(GbStreamServiceImpl.class);
+
+    @Autowired
+    DataSourceTransactionManager dataSourceTransactionManager;
+
+    @Autowired
+    TransactionDefinition transactionDefinition;
+
+    @Autowired
+    private GbStreamMapper gbStreamMapper;
+
+    @Autowired
+    private PlarfotmGbStreamMapper plarfotmGbStreamMapper;
+
+    @Override
+    public PageInfo<GbStream> getAll(Integer page, Integer count) {
+        PageHelper.startPage(page, count);
+        List<GbStream> all = gbStreamMapper.selectAll();
+        return new PageInfo<>(all);
+    }
+
+    @Override
+    public void del(String app, String stream) {
+        gbStreamMapper.del(app, stream);
+    }
+
+
+    @Override
+    public boolean addPlatformInfo(List<GbStream> gbStreams, String platformId) {
+        // 鏀惧湪浜嬪姟鍐呮墽琛�
+        boolean result = false;
+        TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
+        try {
+            for (GbStream gbStream : gbStreams) {
+                gbStream.setPlatformId(platformId);
+                plarfotmGbStreamMapper.add(gbStream);
+            }
+            dataSourceTransactionManager.commit(transactionStatus);     //鎵嬪姩鎻愪氦
+            result = true;
+        }catch (Exception e) {
+            logger.error("鎵归噺淇濆瓨娴佷笌骞冲彴鐨勫叧绯绘椂閿欒", e);
+            dataSourceTransactionManager.rollback(transactionStatus);
+        }
+        return result;
+
+    }
+
+    @Override
+    public boolean delPlatformInfo(List<GbStream> gbStreams) {
+        // 鏀惧湪浜嬪姟鍐呮墽琛�
+        boolean result = false;
+        TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
+        try {
+            for (GbStream gbStream : gbStreams) {
+                plarfotmGbStreamMapper.delByAppAndStream(gbStream.getApp(), gbStream.getStream());
+            }
+            dataSourceTransactionManager.commit(transactionStatus);     //鎵嬪姩鎻愪氦
+            result = true;
+        }catch (Exception e) {
+            logger.error("鎵归噺绉婚櫎娴佷笌骞冲彴鐨勫叧绯绘椂閿欒", e);
+            dataSourceTransactionManager.rollback(transactionStatus);
+        }
+        return result;
+    }
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/MediaServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/MediaServiceImpl.java
index afd6cc9..68a1c44 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/MediaServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/MediaServiceImpl.java
@@ -27,6 +27,8 @@
     public StreamInfo getStreamInfoByAppAndStream(String app, String stream) {
         MediaServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
         StreamInfo streamInfoResult = new StreamInfo();
+        streamInfoResult.setStreamId(stream);
+        streamInfoResult.setApp(app);
         streamInfoResult.setRtmp(String.format("rtmp://%s:%s/%s/%s", mediaInfo.getWanIp(), mediaInfo.getRtmpPort(), app,  stream));
         streamInfoResult.setRtsp(String.format("rtsp://%s:%s/%s/%s", mediaInfo.getWanIp(), mediaInfo.getRtspPort(), app,  stream));
         streamInfoResult.setFlv(String.format("http://%s:%s/%s/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app,  stream));
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java
index edd8710..694c74f 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java
@@ -153,27 +153,8 @@
     public StreamInfo onPublishHandler(JSONObject resonse, String deviceId, String channelId, String uuid) {
         String streamId = resonse.getString("id");
         StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream("rtp", streamId);
-//        StreamInfo streamInfo = new StreamInfo();
-        streamInfo.setStreamId(streamId);
         streamInfo.setDeviceID(deviceId);
         streamInfo.setChannelId(channelId);
-//        MediaServerConfig mediaServerConfig = redisCatchStorage.getMediaInfo();
-
-//        streamInfo.setFlv(String.format("http://%s:%s/rtp/%s.flv", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));
-//        streamInfo.setWs_flv(String.format("ws://%s:%s/rtp/%s.flv", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));
-//
-//        streamInfo.setFmp4(String.format("http://%s:%s/rtp/%s.live.mp4", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));
-//        streamInfo.setWs_fmp4(String.format("ws://%s:%s/rtp/%s.live.mp4", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));
-//
-//        streamInfo.setHls(String.format("http://%s:%s/rtp/%s/hls.m3u8", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));
-//        streamInfo.setWs_hls(String.format("ws://%s:%s/rtp/%s/hls.m3u8", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));
-//
-//        streamInfo.setTs(String.format("http://%s:%s/rtp/%s.live.ts", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));
-//        streamInfo.setWs_ts(String.format("ws://%s:%s/rtp/%s.live.ts", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));
-//
-//        streamInfo.setRtmp(String.format("rtmp://%s:%s/rtp/%s", mediaServerConfig.getWanIp(), mediaServerConfig.getRtmpPort(), streamId));
-//        streamInfo.setRtsp(String.format("rtsp://%s:%s/rtp/%s", mediaServerConfig.getWanIp(), mediaServerConfig.getRtspPort(), streamId));
-
         return streamInfo;
     }
 
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/StreamProxyServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/StreamProxyServiceImpl.java
index 0655980..ec94844 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/StreamProxyServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/StreamProxyServiceImpl.java
@@ -2,20 +2,17 @@
 
 import com.alibaba.fastjson.JSONObject;
 import com.genersoft.iot.vmp.conf.MediaServerConfig;
-import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
-import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyDto;
+import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
+import com.genersoft.iot.vmp.storager.dao.GbStreamMapper;
+import com.genersoft.iot.vmp.storager.dao.PlarfotmGbStreamMapper;
 import com.genersoft.iot.vmp.storager.dao.StreamProxyMapper;
 import com.genersoft.iot.vmp.vmanager.service.IStreamProxyService;
-import com.genersoft.iot.vmp.vmanager.streamProxy.StreamProxyController;
-import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-
-import java.util.List;
 
 /**
  * 瑙嗛浠g悊涓氬姟
@@ -35,29 +32,35 @@
     @Autowired
     private StreamProxyMapper streamProxyMapper;
 
+    @Autowired
+    private GbStreamMapper gbStreamMapper;
+
+    @Autowired
+    private PlarfotmGbStreamMapper plarfotmGbStreamMapper;
+
 
     @Override
-    public void save(StreamProxyDto param) {
+    public void save(StreamProxyItem param) {
         MediaServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
         String dstUrl = String.format("rtmp://%s:%s/%s/%s", "127.0.0.1", mediaInfo.getRtmpPort(), param.getApp(),
                 param.getStream() );
         param.setDst_url(dstUrl);
         // 鏇存柊
         if (videoManagerStorager.queryStreamProxy(param.getApp(), param.getStream()) != null) {
-            int result = videoManagerStorager.updateStreamProxy(param);
-            if (result > 0 && param.isEnable()) {
+            boolean result = videoManagerStorager.updateStreamProxy(param);
+            if (result && param.isEnable()) {
                 addStreamProxyToZlm(param);
             }
         }else { // 鏂板
-            int result = videoManagerStorager.addStreamProxy(param);
-            if (result > 0 && param.isEnable()) {
+            boolean result = videoManagerStorager.addStreamProxy(param);
+            if (result  && param.isEnable()) {
                 addStreamProxyToZlm(param);
             }
         }
     }
 
     @Override
-    public JSONObject addStreamProxyToZlm(StreamProxyDto param) {
+    public JSONObject addStreamProxyToZlm(StreamProxyItem param) {
         JSONObject result = null;
         if ("default".equals(param.getType())){
             result = zlmresTfulUtils.addStreamProxy(param.getApp(), param.getStream(), param.getUrl(),
@@ -70,37 +73,42 @@
     }
 
     @Override
-    public JSONObject removeStreamProxyFromZlm(StreamProxyDto param) {
+    public JSONObject removeStreamProxyFromZlm(StreamProxyItem param) {
         JSONObject result = zlmresTfulUtils.closeStreams(param.getApp(), param.getStream());
+
         return result;
     }
 
     @Override
-    public PageInfo<StreamProxyDto> getAll(Integer page, Integer count) {
+    public PageInfo<StreamProxyItem> getAll(Integer page, Integer count) {
         return videoManagerStorager.queryStreamProxyList(page, count);
     }
 
     @Override
     public void del(String app, String stream) {
-        StreamProxyDto streamProxyDto = new StreamProxyDto();
-        streamProxyDto.setApp(app);
-        streamProxyDto.setStream(stream);
-        JSONObject jsonObject = removeStreamProxyFromZlm(streamProxyDto);
+        StreamProxyItem streamProxyItem = new StreamProxyItem();
+        streamProxyItem.setApp(app);
+        streamProxyItem.setStream(stream);
+        JSONObject jsonObject = removeStreamProxyFromZlm(streamProxyItem);
         if (jsonObject.getInteger("code") == 0) {
             videoManagerStorager.deleteStreamProxy(app, stream);
+            // 濡傛灉鍏宠仈浜嗗浗鏍囬偅涔堢Щ闄ゅ叧鑱�
+            gbStreamMapper.del(app, stream);
+            plarfotmGbStreamMapper.delByAppAndStream(app, stream);
+            // TODO 濡傛灉鍏宠仈鐨勬帹娴侊紝 閭d箞鐘舵�佽缃负绂荤嚎
         }
     }
 
     @Override
     public boolean start(String app, String stream) {
         boolean result = false;
-        StreamProxyDto streamProxyDto = videoManagerStorager.queryStreamProxy(app, stream);
-        if (!streamProxyDto.isEnable() &&  streamProxyDto != null) {
-            JSONObject jsonObject = addStreamProxyToZlm(streamProxyDto);
+        StreamProxyItem streamProxy = videoManagerStorager.queryStreamProxy(app, stream);
+        if (!streamProxy.isEnable() &&  streamProxy != null) {
+            JSONObject jsonObject = addStreamProxyToZlm(streamProxy);
             if (jsonObject.getInteger("code") == 0) {
                 result = true;
-                streamProxyDto.setEnable(true);
-                videoManagerStorager.updateStreamProxy(streamProxyDto);
+                streamProxy.setEnable(true);
+                videoManagerStorager.updateStreamProxy(streamProxy);
             }
         }
         return result;
@@ -109,7 +117,7 @@
     @Override
     public boolean stop(String app, String stream) {
         boolean result = false;
-        StreamProxyDto streamProxyDto = videoManagerStorager.queryStreamProxy(app, stream);
+        StreamProxyItem streamProxyDto = videoManagerStorager.queryStreamProxy(app, stream);
         if (streamProxyDto.isEnable() &&  streamProxyDto != null) {
             JSONObject jsonObject = removeStreamProxyFromZlm(streamProxyDto);
             if (jsonObject.getInteger("code") == 0) {
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 09d4174..95b83ef 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,8 +1,7 @@
 package com.genersoft.iot.vmp.vmanager.streamProxy;
 
 import com.alibaba.fastjson.JSONObject;
-import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
-import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyDto;
+import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.vmanager.service.IStreamProxyService;
 import com.github.pagehelper.PageInfo;
@@ -31,17 +30,17 @@
 
     @RequestMapping(value = "/list")
     @ResponseBody
-    public PageInfo<StreamProxyDto> list(@RequestParam(required = false)Integer page,
-                                         @RequestParam(required = false)Integer count,
-                                         @RequestParam(required = false)String q,
-                                         @RequestParam(required = false)Boolean online ){
+    public PageInfo<StreamProxyItem> list(@RequestParam(required = false)Integer page,
+                                          @RequestParam(required = false)Integer count,
+                                          @RequestParam(required = false)String q,
+                                          @RequestParam(required = false)Boolean online ){
 
         return streamProxyService.getAll(page, count);
     }
 
     @RequestMapping(value = "/save")
     @ResponseBody
-    public Object save(@RequestBody StreamProxyDto param){
+    public Object save(@RequestBody StreamProxyItem param){
         logger.info("娣诲姞浠g悊锛� " + JSONObject.toJSONString(param));
         streamProxyService.save(param);
         return "success";
diff --git a/src/main/resources/wvp.sqlite b/src/main/resources/wvp.sqlite
index 9147e22..315c689 100644
--- a/src/main/resources/wvp.sqlite
+++ b/src/main/resources/wvp.sqlite
Binary files differ
diff --git a/web_src/src/components/PLatformStreamList.vue b/web_src/src/components/PLatformStreamList.vue
new file mode 100644
index 0000000..ef5b5ec
--- /dev/null
+++ b/web_src/src/components/PLatformStreamList.vue
@@ -0,0 +1,283 @@
+<template>
+	<div id="pLatformStreamList">
+		<el-container>
+			<el-header>
+				<uiHeader></uiHeader>
+			</el-header>
+			<el-main>
+				<div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">
+					<span style="font-size: 1rem; font-weight: bold;">鐩存挱绾ц仈鍒楄〃</span>
+				</div>
+				<div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;">
+					<el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addStreamProxy">娣诲姞浠g悊</el-button>
+				</div>
+				<devicePlayer ref="devicePlayer"></devicePlayer>
+				<el-table :data="streamProxyList" border style="width: 100%" :height="winHeight">
+					<el-table-column prop="app" label="搴旂敤鍚�" align="center" show-overflow-tooltip/>
+					<el-table-column prop="stream" label="娴両D" align="center" show-overflow-tooltip/>
+					<el-table-column prop="gbId" label="鍥芥爣骞冲彴" align="center" show-overflow-tooltip/>
+					
+					<el-table-column label="杞琀LS" width="120" align="center">
+						<template slot-scope="scope">
+						<div slot="reference" class="name-wrapper">
+							<el-tag size="medium" v-if="scope.row.enable_hls">宸插惎鐢�</el-tag>
+							<el-tag size="medium" type="info" v-if="!scope.row.enable_hls">鏈惎鐢�</el-tag>
+						</div>
+						</template>
+					</el-table-column>
+					<el-table-column label="MP4褰曞埗" width="120" align="center">
+						<template slot-scope="scope">
+						<div slot="reference" class="name-wrapper">
+							<el-tag size="medium" v-if="scope.row.enable_mp4">宸插惎鐢�</el-tag>
+							<el-tag size="medium" type="info" v-if="!scope.row.enable_mp4">鏈惎鐢�</el-tag>
+						</div>
+						</template>
+					</el-table-column>
+					<el-table-column label="鍚敤" width="120" align="center">
+						<template slot-scope="scope">
+						<div slot="reference" class="name-wrapper">
+							<el-tag size="medium" v-if="scope.row.enable">宸插惎鐢�</el-tag>
+							<el-tag size="medium" type="info" v-if="!scope.row.enable">鏈惎鐢�</el-tag>
+						</div>
+						</template>
+					</el-table-column>
+
+					<el-table-column label="鎿嶄綔" width="360" align="center" fixed="right">
+						<template slot-scope="scope">
+							<el-button-group>
+								<el-button size="mini" icon="el-icon-video-play" v-if="scope.row.enable" @click="play(scope.row)">鎾斁</el-button>
+								<el-button size="mini" icon="el-icon-close" type="success" v-if="scope.row.enable" @click="stop(scope.row)">鍋滅敤</el-button>
+								<el-button size="mini" icon="el-icon-check" type="primary" v-if="!scope.row.enable" @click="start(scope.row)">鍚敤</el-button>
+								<el-button size="mini" icon="el-icon-delete" type="danger"  @click="deleteStreamProxy(scope.row)">鍒犻櫎</el-button>
+								<!-- <el-button size="mini" icon="el-icon-position" type="primary"  >鍔犲叆鍥芥爣</el-button> -->
+							</el-button-group>
+							</template>
+					</el-table-column>
+				</el-table>
+				<el-pagination
+					style="float: right"
+					@size-change="handleSizeChange"
+					@current-change="currentChange"
+					:current-page="currentPage"
+					:page-size="count"
+					:page-sizes="[15, 25, 35, 50]"
+					layout="total, sizes, prev, pager, next"
+					:total="total">
+				</el-pagination>
+			<streamProxyEdit ref="streamProxyEdit" ></streamProxyEdit>
+			</el-main>
+		</el-container>
+	</div>
+</template>
+
+<script>
+	import streamProxyEdit from './dialog/StreamProxyEdit.vue'
+	import devicePlayer from './dialog/devicePlayer.vue'
+	import uiHeader from './UiHeader.vue'
+	export default {
+		name: 'pLatformStreamList',
+		components: {
+			devicePlayer,
+			streamProxyEdit,
+			uiHeader
+		},
+		data() {
+			return {
+				streamProxyList: [], 
+				currentPusher: {}, //褰撳墠鎿嶄綔璁惧瀵硅薄
+				updateLooper: 0, //鏁版嵁鍒锋柊杞鏍囧織
+				currentDeviceChannelsLenth:0,
+				winHeight: window.innerHeight - 200,
+				currentPage:1,
+				count:15,
+				total:0,
+				getListLoading: false
+			};
+		},
+		computed: {
+		},
+		mounted() {
+			this.initData();
+			// this.updateLooper = setInterval(this.initData, 10000);
+		},
+		destroyed() {
+			this.$destroy('videojs');
+			clearTimeout(this.updateLooper);
+		},
+		methods: {
+			initData: function() {
+				this.getStreamProxyList();
+			},
+			currentChange: function(val){
+				this.currentPage = val;
+				this.getStreamProxyList();
+			},
+			handleSizeChange: function(val){
+				this.count = val;
+				this.getStreamProxyList();
+			},
+			getStreamProxyList: function() {
+				let that = this;
+				this.getListLoading = true;
+				this.$axios.get(`/api/proxy/list`,{
+					params: {
+						page: that.currentPage,
+						count: that.count
+					}
+				} )
+				.then(function (res) {
+					console.log(res);
+					console.log(res.data.list);
+					that.total = res.data.total;
+					that.streamProxyList = res.data.list;
+					that.getListLoading = false;
+				})
+				.catch(function (error) {
+					console.log(error);
+					that.getListLoading = false;
+				});
+			},
+			addStreamProxy: function(){
+				this.$refs.streamProxyEdit.openDialog(null, this.initData)
+			},
+			saveStreamProxy: function(){
+			},
+			play: function(row){
+				let that = this;
+				this.getListLoading = true;
+				this.$axios.get(`/api/media/getStreamInfoByAppAndStream`,{
+					params: {
+						app: row.app,
+						stream: row.stream
+					}
+				})
+				.then(function (res) {
+					that.getListLoading = false;
+					that.$refs.devicePlayer.openDialog("streamPlay", null, null, {
+                        streamInfo: res.data,
+                        hasAudio: true
+                    });
+				})
+				.catch(function (error) {
+					console.log(error);
+					that.getListLoading = false;
+				});
+				
+			},
+			deleteStreamProxy: function(row){
+				console.log(1111)
+				let that = this;
+				this.getListLoading = true;
+				this.$axios.get(`/api/proxy/del`,{
+					params: {
+						app: row.app,
+						stream: row.stream
+					}
+				})
+				.then(function (res) {
+					that.getListLoading = false;
+					that.initData()
+				})
+				.catch(function (error) {
+					console.log(error);
+					that.getListLoading = false;
+				});
+			},
+			start: function(row){
+				let that = this;
+				this.getListLoading = true;
+				this.$axios.get(`/api/proxy/start`,{
+					params: {
+						app: row.app,
+						stream: row.stream
+					}
+				})
+				.then(function (res) {
+					that.getListLoading = false;
+					that.initData()
+				})
+				.catch(function (error) {
+					console.log(error);
+					that.getListLoading = false;
+				});
+			},
+			stop: function(row){
+				let that = this;
+				this.getListLoading = true;
+				this.$axios.get(`/api/proxy/stop`,{
+					params: {
+						app: row.app,
+						stream: row.stream
+					}
+				})
+				.then(function (res) {
+					that.getListLoading = false;
+					that.initData()
+				})
+				.catch(function (error) {
+					console.log(error);
+					that.getListLoading = false;
+				});
+			}
+
+		}
+	};
+</script>
+
+<style>
+	.videoList {
+		display: flex;
+		flex-wrap: wrap;
+		align-content: flex-start;
+	}
+
+	.video-item {
+		position: relative;
+		width: 15rem;
+		height: 10rem;
+		margin-right: 1rem;
+		background-color: #000000;
+	}
+
+	.video-item-img {
+		position: absolute;
+		top: 0;
+		bottom: 0;
+		left: 0;
+		right: 0;
+		margin: auto;
+		width: 100%;
+		height: 100%;
+	}
+
+	.video-item-img:after {
+		content: "";
+		display: inline-block;
+		position: absolute;
+		z-index: 2;
+		top: 0;
+		bottom: 0;
+		left: 0;
+		right: 0;
+		margin: auto;
+		width: 3rem;
+		height: 3rem;
+		background-image: url("../assets/loading.png");
+		background-size: cover;
+		background-color: #000000;
+	}
+
+	.video-item-title {
+		position: absolute;
+		bottom: 0;
+		color: #000000;
+		background-color: #ffffff;
+		line-height: 1.5rem;
+		padding: 0.3rem;
+		width: 14.4rem;
+	}
+	.cpoy-btn {
+		cursor: pointer;
+		margin-right: 10px;
+	}
+</style>
diff --git a/web_src/src/components/ParentPlatformList.vue b/web_src/src/components/ParentPlatformList.vue
index 32c999d..1121f6e 100644
--- a/web_src/src/components/ParentPlatformList.vue
+++ b/web_src/src/components/ParentPlatformList.vue
@@ -19,7 +19,7 @@
             <template slot-scope="scope">
               <div slot="reference" class="name-wrapper">
                 <el-tag size="medium" v-if="scope.row.enable">宸插惎鐢�</el-tag>
-                <el-tag size="medium" v-if="!scope.row.enable">鏈惎鐢�</el-tag>
+                <el-tag size="medium" type="info" v-if="!scope.row.enable">鏈惎鐢�</el-tag>
               </div>
             </template>
           </el-table-column>
diff --git a/web_src/src/components/PushVideoList.vue b/web_src/src/components/PushVideoList.vue
index 4a93d7a..bbfc5f8 100644
--- a/web_src/src/components/PushVideoList.vue
+++ b/web_src/src/components/PushVideoList.vue
@@ -19,10 +19,14 @@
 					</el-table-column>
 					<el-table-column prop="totalReaderCount" label="鍦ㄧ嚎浜烘暟" width="240" align="center">
 					</el-table-column>
-					<el-table-column prop="createStamp" label="寮�濮嬫椂闂�" align="center">
+					<el-table-column label="寮�濮嬫椂闂�" align="center" >
+						<template slot-scope="scope">
+							<el-button-group>
+								{{dateFormat(parseInt(scope.row.createStamp))}}
+							</el-button-group>
+							</template>
 					</el-table-column>
 					
-
 					<el-table-column label="鎿嶄綔" width="360" align="center" fixed="right">
 						<template slot-scope="scope">
 							<el-button-group>
@@ -144,6 +148,19 @@
 			},
 			stopPuhsh: function(row){
 				console.log(row)
+			},
+			dateFormat: function(/** timestamp=0 **/) {
+				var ts = arguments[0] || 0;
+				var t,y,m,d,h,i,s;
+				t = ts ? new Date(ts*1000) : new Date();
+				y = t.getFullYear();
+				m = t.getMonth()+1;
+				d = t.getDate();
+				h = t.getHours();
+				i = t.getMinutes();
+				s = t.getSeconds();
+				// 鍙牴鎹渶瑕佸湪杩欓噷瀹氫箟鏃堕棿鏍煎紡
+				return y+'-'+(m<10?'0'+m:m)+'-'+(d<10?'0'+d:d)+' '+(h<10?'0'+h:h)+':'+(i<10?'0'+i:i)+':'+(s<10?'0'+s:s);
 			}
 
 		}
diff --git a/web_src/src/components/StreamProxyList.vue b/web_src/src/components/StreamProxyList.vue
index 0a1e03d..f76a164 100644
--- a/web_src/src/components/StreamProxyList.vue
+++ b/web_src/src/components/StreamProxyList.vue
@@ -13,7 +13,8 @@
 				</div>
 				<devicePlayer ref="devicePlayer"></devicePlayer>
 				<el-table :data="streamProxyList" border style="width: 100%" :height="winHeight">
-					<el-table-column prop="app" label="搴旂敤鍚�" align="center" show-overflow-tooltip/>
+					<el-table-column prop="name" label="鍚嶇О" align="center" show-overflow-tooltip/>
+					<el-table-column prop="app" label="娴佸簲鐢ㄥ悕" align="center" show-overflow-tooltip/>
 					<el-table-column prop="stream" label="娴両D" align="center" show-overflow-tooltip/>
 					<el-table-column label="娴佸湴鍧�" width="400" align="center" show-overflow-tooltip >
 						<template slot-scope="scope">
@@ -30,7 +31,7 @@
 						</div>
 						</template>
 					</el-table-column>
-
+					<el-table-column prop="gbId" label="鍥芥爣缂栫爜" width="180" align="center" show-overflow-tooltip/>
 					<el-table-column label="杞琀LS" width="120" align="center">
 						<template slot-scope="scope">
 						<div slot="reference" class="name-wrapper">
@@ -56,7 +57,6 @@
 						</template>
 					</el-table-column>
 
-					
 					<el-table-column label="鎿嶄綔" width="360" align="center" fixed="right">
 						<template slot-scope="scope">
 							<el-button-group>
@@ -64,6 +64,7 @@
 								<el-button size="mini" icon="el-icon-close" type="success" v-if="scope.row.enable" @click="stop(scope.row)">鍋滅敤</el-button>
 								<el-button size="mini" icon="el-icon-check" type="primary" v-if="!scope.row.enable" @click="start(scope.row)">鍚敤</el-button>
 								<el-button size="mini" icon="el-icon-delete" type="danger"  @click="deleteStreamProxy(scope.row)">鍒犻櫎</el-button>
+								<!-- <el-button size="mini" icon="el-icon-position" type="primary"  >鍔犲叆鍥芥爣</el-button> -->
 							</el-button-group>
 							</template>
 					</el-table-column>
diff --git a/web_src/src/components/dialog/StreamProxyEdit.vue b/web_src/src/components/dialog/StreamProxyEdit.vue
index a2b3c9e..63a7bf6 100644
--- a/web_src/src/components/dialog/StreamProxyEdit.vue
+++ b/web_src/src/components/dialog/StreamProxyEdit.vue
@@ -21,7 +21,10 @@
                   <el-option label="FFmpeg" value="ffmpeg"></el-option>
                 </el-select>
               </el-form-item>
-              <el-form-item label="搴旂敤鍚�" prop="app">
+              <el-form-item label="鍚嶇О" prop="name">
+                <el-input v-model="proxyParam.name" clearable></el-input>
+              </el-form-item>
+              <el-form-item label="娴佸簲鐢ㄥ悕" prop="app">
                 <el-input v-model="proxyParam.app" clearable></el-input>
               </el-form-item>
               <el-form-item label="娴両D" prop="stream">
@@ -38,6 +41,9 @@
               </el-form-item>
               <el-form-item label="FFmpeg鍛戒护妯℃澘" prop="ffmpeg_cmd_key" v-if="proxyParam.type=='ffmpeg'">
                 <el-input v-model="proxyParam.ffmpeg_cmd_key" clearable></el-input>
+              </el-form-item>
+              <el-form-item label="鍥芥爣缂栫爜" prop="gbId">
+                <el-input v-model="proxyParam.gbId" placeholder="璁剧疆鍥芥爣缂栫爜鍙帹閫佸埌鍥芥爣" clearable></el-input>
               </el-form-item>
               <el-form-item label="鎷夋祦鏂瑰紡" prop="rtp_type" v-if="proxyParam.type=='default'">
                 <el-select
@@ -100,6 +106,7 @@
       isLoging: false,
       onSubmit_text: "绔嬪嵆鍒涘缓",
       proxyParam: {
+          name: null,
           type: "default",
           app: null,
           stream: null,
@@ -107,6 +114,7 @@
           src_url: null,
           timeout_ms: null,
           ffmpeg_cmd_key: null,
+          gbId: null,
           rtp_type: null,
           enable: true,
           enable_hls: true,
@@ -114,6 +122,7 @@
       },
       
       rules: {
+        name: [{ required: true, message: "璇疯緭鍏ュ悕绉�", trigger: "blur" }],
         app: [{ required: true, message: "璇疯緭鍏ュ簲鐢ㄥ悕", trigger: "blur" }],
         stream: [{ required: true, message: "璇疯緭鍏ユ祦ID", trigger: "blur" }],
         url: [{ required: true, message: "璇疯緭鍏ヨ浠g悊鐨勬祦", trigger: "blur" }],
diff --git a/web_src/src/components/dialog/chooseChannel.vue b/web_src/src/components/dialog/chooseChannel.vue
index 219036c..31ef4b7 100644
--- a/web_src/src/components/dialog/chooseChannel.vue
+++ b/web_src/src/components/dialog/chooseChannel.vue
@@ -13,7 +13,11 @@
 
             </el-tab-pane>
             <el-tab-pane label="鐩存挱娴侀�氶亾" name="streamchannel">
-                <!-- TODO -->
+                <el-container>
+                    <el-main style="background-color: #FFF;">
+                     <chooseChannelFoStream :platformId=platformId ></chooseChannelFoStream>
+                    </el-main>
+            </el-container>
             </el-tab-pane>
         </el-tabs>
     </el-dialog>
@@ -22,11 +26,13 @@
 
 <script>
 import chooseChannelForGb from '../dialog/chooseChannelForGb.vue'
+import chooseChannelFoStream from '../dialog/chooseChannelForStream.vue'
 export default {
     name: 'chooseChannel',
     props: {},
     components: {
         chooseChannelForGb,
+        chooseChannelFoStream,
     },
     computed: {
         // getPlayerShared: function () {
diff --git a/web_src/src/components/dialog/chooseChannelForGb.vue b/web_src/src/components/dialog/chooseChannelForGb.vue
index b21416c..22b6032 100644
--- a/web_src/src/components/dialog/chooseChannelForGb.vue
+++ b/web_src/src/components/dialog/chooseChannelForGb.vue
@@ -27,7 +27,7 @@
         <el-table-column type="selection" width="55" align="center" fixed > </el-table-column>
         <el-table-column prop="channelId" label="閫氶亾缂栧彿" width="210">
         </el-table-column>
-        <el-table-column prop="name" label="閫氶亾鍚嶇О">
+        <el-table-column prop="name" label="閫氶亾鍚嶇О" show-overflow-tooltip>
         </el-table-column>
         <el-table-column prop="deviceId" label="璁惧缂栧彿" width="210" >
         </el-table-column>
diff --git a/web_src/src/components/dialog/chooseChannelForStream.vue b/web_src/src/components/dialog/chooseChannelForStream.vue
new file mode 100644
index 0000000..0824cbb
--- /dev/null
+++ b/web_src/src/components/dialog/chooseChannelForStream.vue
@@ -0,0 +1,215 @@
+<template>
+<div id="chooseChannelFoStream" >
+    <el-table ref="gbStreamsTable" :data="gbStreams" border style="width: 100%" @selection-change="checkedChanage" >
+        <el-table-column type="selection" width="55" align="center" fixed > </el-table-column>
+        <el-table-column prop="name" label="鍚嶇О" show-overflow-tooltip>
+        </el-table-column>
+        <el-table-column prop="app" label="搴旂敤鍚�" show-overflow-tooltip>
+        </el-table-column>
+        <el-table-column prop="stream" label="娴両D"  show-overflow-tooltip>
+        </el-table-column>
+        <el-table-column prop="gbId" label="鍥芥爣缂栫爜" show-overflow-tooltip>
+        </el-table-column>
+        <el-table-column prop="streamType" label="娴佹潵婧�" align="center" show-overflow-tooltip>
+        </el-table-column>
+        <el-table-column label="娴佹潵婧�" width="100" align="center">
+            <template slot-scope="scope">
+            <div slot="reference" class="name-wrapper">
+                <el-tag size="medium" v-if="scope.row.streamType == 'proxy'">鎷夋祦浠g悊</el-tag>
+                <el-tag size="medium" v-if="scope.row.streamType == 'push'">鎺ㄦ祦</el-tag>
+            </div>
+            </template>
+        </el-table-column>
+    </el-table>
+    <el-pagination style="float: right;margin-top: 1rem;" @size-change="handleSizeChange" @current-change="currentChange" :current-page="currentPage" :page-size="count" :page-sizes="[10, 20, 30, 50]" layout="total, sizes, prev, pager, next" :total="total">
+    </el-pagination>
+</div>
+</template>
+
+<script>
+export default {
+    name: 'chooseChannelFoStream',
+    props: {},
+    computed: {
+        // getPlayerShared: function () {
+        //     return {
+        //         sharedUrl: window.location.host + '/' + this.videoUrl,
+        //         sharedIframe: '<iframe src="' + window.location.host + '/' + this.videoUrl + '"></iframe>',
+        //         sharedRtmp: this.videoUrl
+        //     };
+        // }
+    },
+    props: ['platformId'],
+    created() {
+        this.initData();
+    },
+    data() {
+        return {
+            gbStreams: [],
+            gbChoosechannel:{},
+            searchSrt: "",
+            channelType: "",
+            online: "",
+            choosed: "",
+            currentPage: 0,
+            count: 10,
+            total: 0,
+            eventEnanle: false
+
+        };
+    },
+    watch:{
+        platformId(newData, oldData){
+            console.log(newData)
+            this.initData()
+            
+        },
+    },
+    methods: {
+        initData: function() {
+            this.getChannelList();
+        },
+        currentChange: function (val) {
+            this.currentPage = val;
+            this.initData();
+        },
+        handleSizeChange: function (val) {
+            this.count = val;
+            console.log(val)
+            this.initData();
+
+        },
+        rowcheckedChanage: function (val, row) {
+            console.log(val)
+            console.log(row)
+        },
+        checkedChanage: function (val) {
+            var that = this;
+            if (!that.eventEnanle) {
+                return;
+            }
+            var tabelData = JSON.parse(JSON.stringify(this.$refs.gbStreamsTable.data));
+            console.log("checkedChanage")
+            console.log(val)
+
+            var newData = {};
+            var addData = [];
+            var delData = [];
+            if (val.length > 0) {
+                for (let i = 0; i < val.length; i++) {
+                    const element = val[i];
+                    var key = element.app + "_" + element.stream;
+                    newData[key] = element;
+                    if (!!!that.gbChoosechannel[key]){
+                        addData.push(element)
+                    }else{
+                        delete that.gbChoosechannel[key]
+                    }
+                }
+                 
+                 var oldKeys = Object.keys(that.gbChoosechannel);
+                if (oldKeys.length > 0) {
+                    for (let i = 0; i < oldKeys.length; i++) {
+                        const key = oldKeys[i];
+                        delData.push(that.gbChoosechannel[key])
+                    }
+                }
+                
+            }else{
+                var oldKeys = Object.keys(that.gbChoosechannel);
+                if (oldKeys.length > 0) {
+                    for (let i = 0; i < oldKeys.length; i++) {
+                        const key = oldKeys[i];
+                        delData.push(that.gbChoosechannel[key])
+                    }
+                }
+            }
+
+            that.gbChoosechannel = newData;
+            if (Object.keys(addData).length >0) {
+                console.log(addData)
+                that.$axios({
+                    method:"post",
+                     url:"/api/gbStream/add",
+                    data:{
+                        platformId: that.platformId,
+                        gbStreams:  addData,
+                    }
+                }).then((res)=>{
+                    console.log("淇濆瓨鎴愬姛")
+                }).catch(function (error) {
+                    console.log(error);
+                });
+            }
+            if (Object.keys(delData).length >0) {
+                console.log(delData)
+                 that.$axios({
+                    method:"post",
+                    url:"/api/gbStream/del",
+                    data:{
+                        gbStreams:  delData,
+                    }
+                }).then((res)=>{
+                    console.log("绉婚櫎鎴愬姛")
+                }).catch(function (error) {
+                    console.log(error);
+                });
+            }
+
+        },
+        shareAllCheckedChanage: function (val) {
+            this.chooseChanage(null, val)
+        },
+        getChannelList: function () {
+            let that = this;
+
+            this.$axios.get(`/api/gbStream/list`, {
+                    params: {
+                        page: that.currentPage,
+                        count: that.count,
+                        query: that.searchSrt,
+                        online: that.online,
+                        choosed: that.choosed,
+                        platformId: that.platformId,
+                        channelType: that.channelType
+                    }
+                })
+                .then(function (res) {
+                    that.total = res.data.total;
+                    that.gbStreams = res.data.list;
+                    that.gbChoosechannel = {};
+                    // 闃叉鍑虹幇琛ㄦ牸閿欎綅
+                    that.$nextTick(() => {
+                        that.$refs.gbStreamsTable.doLayout();
+                        // 榛樿閫変腑
+                        var chooseGBS = [];
+                        for (let i = 0; i < res.data.list.length; i++) {
+                            const row = res.data.list[i];
+                            console.log(row.platformId)
+                            if (row.platformId == that.platformId) {
+                                that.$refs.gbStreamsTable.toggleRowSelection(row, true);
+                                chooseGBS.push(row)
+                                that.gbChoosechannel[row.app+ "_" + row.stream] = row;
+                               
+                            }
+                        }
+                         that.eventEnanle = true;
+                        // that.checkedChanage(chooseGBS)
+                    })
+                    console.log(that.gbChoosechannel)
+                })
+                .catch(function (error) {
+                    console.log(error);
+                });
+
+        },
+        handleGBSelectionChange: function() {
+            this.initData();
+        },
+    }
+};
+</script>
+
+<style>
+
+</style>
diff --git a/web_src/src/components/dialog/devicePlayer.vue b/web_src/src/components/dialog/devicePlayer.vue
index 48d295a..6780095 100644
--- a/web_src/src/components/dialog/devicePlayer.vue
+++ b/web_src/src/components/dialog/devicePlayer.vue
@@ -163,6 +163,7 @@
             },
             showVideoDialog: false,
             streamId: '',
+            app : '',
             convertKey: '',
             deviceId: '',
             channelId: '',
@@ -198,7 +199,7 @@
             if (tab.name == "codec") {
                 this.$axios({
                     method: 'get',
-                    url: '/zlm/index/api/getMediaInfo?vhost=__defaultVhost__&schema=rtmp&app=rtp&stream='+ this.streamId
+                    url: '/zlm/index/api/getMediaInfo?vhost=__defaultVhost__&schema=rtmp&app='+ this.app +'&stream='+ this.streamId
                 }).then(function (res) {
                     that.tracksLoading = false;
                     if (res.data.code == 0 && res.data.online) {
@@ -218,6 +219,7 @@
             this.channelId = channelId;
             this.deviceId = deviceId;
             this.streamId = "";
+            this.app = "";
             this.videoUrl = ""
             if (!!this.$refs.videoPlayer) {
                 this.$refs.videoPlayer.pause();
@@ -228,11 +230,11 @@
                     break;
                 case "record":
                     this.showVideoDialog = true;
-
                     this.videoHistory.date = param.date;
                     this.queryRecords()
                     break;
                 case "streamPlay":
+                    this.tabActiveName = "media";
                     this.showRrecord = false,
                     this.showPtz = false,
                     this.play(param.streamInfo, param.hasAudio)
@@ -250,6 +252,7 @@
             this.isLoging = false;
             this.videoUrl = streamInfo.ws_flv;
             this.streamId = streamInfo.streamId;
+            this.app = streamInfo.app;
             this.playFromStreamInfo(false, streamInfo)
         },
         coverPlay: function () {
diff --git a/web_src/src/router/index.js b/web_src/src/router/index.js
index 4735e62..3df0823 100644
--- a/web_src/src/router/index.js
+++ b/web_src/src/router/index.js
@@ -6,6 +6,7 @@
 import channelList from '../components/channelList.vue'
 import pushVideoList from '../components/PushVideoList.vue'
 import streamProxyList from '../components/StreamProxyList.vue'
+import pLatformStreamList from '../components/PLatformStreamList.vue'
 import devicePosition from  '../components/devicePosition.vue'
 import login from '../components/Login.vue'
 import parentPlatformList from '../components/ParentPlatformList.vue'
@@ -34,6 +35,10 @@
       component: pushVideoList,
     },
     {
+      path: '/pLatformStreamList',
+      component: pLatformStreamList,
+    },
+    {
       path: '/streamProxyList',
       component: streamProxyList,
     },

--
Gitblit v1.8.0