瀏覽代碼

Merge branch '648540858:wvp-28181-2.0' into wvp-28181-2.0

mk1990 3 年之前
父節點
當前提交
6bab3b6740

+ 35 - 11
README.md

@@ -109,21 +109,45 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git
 - [X] 支持使用mysql作为数据库,默认sqlite3,开箱即用。
 - [X] WEB端支持播放H264与H265,音频支持G.711A/G.711U/AAC,覆盖国标常用编码格式。
 
-# docker快速体验
-目前作者的docker-compose因为时间有限维护不及时,这里提供第三方提供的供大家使用,维护不易,大家记得给这位小伙伴点个star。  
-https://github.com/SaltFish001/wvp_pro_compose
-[https://github.com/SaltFish001/wvp_pro_compose](https://github.com/SaltFish001/wvp_pro_compose)
-这是作者维护的一个镜像,可能存在不及时的问题。
-```shell
-docker pull 648540858/wvp_pro
-
-docker run  --env WVP_IP="你的IP" -it -p 18080:18080 -p 30000-30500:30000-30500/udp -p 30000-30500:30000-30500/tcp -p 80:80 -p 5060:5060 -p 5060:5060/udp 648540858/wvp_pro
-```
-docker使用详情查看:[https://hub.docker.com/r/648540858/wvp_pro](https://hub.docker.com/r/648540858/wvp_pro)
+[//]: # (# docker快速体验)
+
+[//]: # (目前作者的docker-compose因为时间有限维护不及时,这里提供第三方提供的供大家使用,维护不易,大家记得给这位小伙伴点个star。  )
+
+[//]: # (https://github.com/SaltFish001/wvp_pro_compose)
+
+[//]: # ([https://github.com/SaltFish001/wvp_pro_compose](https://github.com/SaltFish001/wvp_pro_compose))
+
+[//]: # (这是作者维护的一个镜像,可能存在不及时的问题。)
+
+[//]: # (```shell)
+
+[//]: # (docker pull 648540858/wvp_pro)
+
+[//]: # ()
+[//]: # (docker run  --env WVP_IP="你的IP" -it -p 18080:18080 -p 30000-30500:30000-30500/udp -p 30000-30500:30000-30500/tcp -p 80:80 -p 5060:5060 -p 5060:5060/udp 648540858/wvp_pro)
+
+[//]: # (```)
+
+[//]: # (docker使用详情查看:[https://hub.docker.com/r/648540858/wvp_pro](https://hub.docker.com/r/648540858/wvp_pro))
 
 # gitee同步仓库
 https://gitee.com/pan648540858/wvp-GB28181-pro.git  
 
+# 遇到问题
+国标最麻烦的地方在于设备的兼容性,所以需要大量的设备来测试,目前作者手里的设备有限,再加上作者水平有限,所以遇到问题在所难免;
+1. 查看wiki,仔细的阅读可以帮你避免几乎所有的问题
+2. 搜索issues,这里有大部分的答案
+3. 加QQ群,这里有大量热心的小伙伴,但是前提新希望你已经仔细阅读了wiki和搜索了issues。
+4. 你可以请作者为你解答,但是我不是免费的。
+5. 你可以把遇到问题的设备寄给我,可以更容易的复现问题。
+
+
+# 合作
+目前很多打着合作的幌子来私聊的,其实大家大可不必,目前作者没有精力,你有问题可以付费找我解答,也可以提PR
+,如果对代码有建议可以提ISSUE;也可以加群一起聊聊。我们欢迎所有有兴趣但遇到项目中来的人。
+
+
+
 # 使用帮助
 QQ群: 901799015, ZLM使用文档[https://github.com/ZLMediaKit/ZLMediaKit](https://github.com/ZLMediaKit/ZLMediaKit)  
 QQ私信一般不回, 精力有限.欢迎大家在群里讨论.觉得项目对你有帮助,欢迎star和提交pr。

+ 4 - 0
pom.xml

@@ -256,6 +256,7 @@
 			<plugin>
 				<groupId>org.springframework.boot</groupId>
 				<artifactId>spring-boot-maven-plugin</artifactId>
+				<version>2.3.5.RELEASE</version>
 				<configuration>
 					<includeSystemScope>true</includeSystemScope>
 				</configuration>
@@ -263,6 +264,7 @@
 			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
 				<artifactId>maven-compiler-plugin</artifactId>
+				<version>3.8.1</version>
 				<configuration>
 					<source>1.8</source>
 					<target>1.8</target>
@@ -272,6 +274,7 @@
 			<plugin>
 				<groupId>pl.project13.maven</groupId>
 				<artifactId>git-commit-id-plugin</artifactId>
+				<version>3.0.1</version>
 				<configuration>
 					<offline>true</offline>
 				</configuration>
@@ -280,6 +283,7 @@
 			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
 				<artifactId>maven-surefire-plugin</artifactId>
+				<version>2.22.2</version>
 				<configuration>
 					<skipTests>true</skipTests>
 				</configuration>

+ 16 - 2
src/main/java/com/genersoft/iot/vmp/domain/req/PresetQuerySipReq.java

@@ -1,14 +1,28 @@
 package com.genersoft.iot.vmp.domain.req;
 
-import lombok.Data;
 
 /**
  * @author chenjialing
  */
-@Data
 public class PresetQuerySipReq {
 
     private String presetId;
 
     private String presetName;
+
+    public String getPresetId() {
+        return presetId;
+    }
+
+    public void setPresetId(String presetId) {
+        this.presetId = presetId;
+    }
+
+    public String getPresetName() {
+        return presetName;
+    }
+
+    public void setPresetName(String presetName) {
+        this.presetName = presetName;
+    }
 }

+ 37 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java

@@ -76,6 +76,21 @@ public class SendRtpItem {
      */
     private String CallId;
 
+    /**
+     * 发送时,rtp的pt(uint8_t),不传时默认为96
+     */
+    private int pt = 96;
+
+    /**
+     * 发送时,rtp的负载类型。为true时,负载为ps;为false时,为es;
+     */
+    private boolean usePs = true;
+
+    /**
+     * 当usePs 为false时,有效。为1时,发送音频;为0时,发送视频;不传时默认为0
+     */
+    private boolean onlyAudio = false;
+
     /**
      * 播放类型
      */
@@ -221,5 +236,27 @@ public class SendRtpItem {
         this.dialog = dialog;
     }
 
+    public int getPt() {
+        return pt;
+    }
 
+    public void setPt(int pt) {
+        this.pt = pt;
+    }
+
+    public boolean isUsePs() {
+        return usePs;
+    }
+
+    public void setUsePs(boolean usePs) {
+        this.usePs = usePs;
+    }
+
+    public boolean isOnlyAudio() {
+        return onlyAudio;
+    }
+
+    public void setOnlyAudio(boolean onlyAudio) {
+        this.onlyAudio = onlyAudio;
+    }
 }

+ 2 - 2
src/main/java/com/genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java

@@ -30,7 +30,7 @@ public class CatalogDataCatch {
         CatalogData catalogData = data.get(device.getDeviceId());
         if (catalogData == null || catalogData.getStatus().equals(CatalogData.CatalogDataStatus.end)) {
             catalogData = new CatalogData();
-            catalogData.setChannelList(new ArrayList<>());
+            catalogData.setChannelList(Collections.synchronizedList(new ArrayList<>()));
             catalogData.setDevice(device);
             catalogData.setSn(sn);
             catalogData.setStatus(CatalogData.CatalogDataStatus.ready);
@@ -46,7 +46,7 @@ public class CatalogDataCatch {
             catalogData.setSn(sn);
             catalogData.setTotal(total);
             catalogData.setDevice(device);
-            catalogData.setChannelList(new ArrayList<>());
+            catalogData.setChannelList(Collections.synchronizedList(new ArrayList<>()));
             catalogData.setStatus(CatalogData.CatalogDataStatus.runIng);
             catalogData.setLastTime(new Date(System.currentTimeMillis()));
             data.put(deviceId, catalogData);

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

@@ -4,8 +4,12 @@ import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.genersoft.iot.vmp.common.StreamInfo;
 import com.genersoft.iot.vmp.conf.DynamicTask;
+import com.genersoft.iot.vmp.gb28181.bean.InviteStreamType;
+import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
+import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
+import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
 import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
@@ -13,6 +17,8 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
+import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
+import org.ehcache.shadow.org.terracotta.offheapstore.storage.IntegerStorageEngine;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.InitializingBean;
@@ -50,6 +56,9 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
 	@Autowired
     private IRedisCatchStorage redisCatchStorage;
 
+	@Autowired
+	private IVideoManagerStorage storager;
+
 	@Autowired
 	private ZLMRTPServerFactory zlmrtpServerFactory;
 
@@ -62,6 +71,12 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
 	@Autowired
 	private DynamicTask dynamicTask;
 
+	@Autowired
+	private ISIPCommander cmder;
+
+	@Autowired
+	private ISIPCommanderForPlatform commanderForPlatform;
+
 
 	/**   
 	 * 处理  ACK请求
@@ -78,6 +93,7 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
 		if (dialog.getState()== DialogState.CONFIRMED) {
 			String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
 			logger.info("ACK请求: platformGbId->{}", platformGbId);
+			ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformGbId);
 			// 取消设置的超时任务
 			dynamicTask.stop(callIdHeader.getCallId());
 			String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
@@ -94,8 +110,23 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
 			param.put("dst_port", sendRtpItem.getPort());
 			param.put("is_udp", is_Udp);
 			param.put("src_port", sendRtpItem.getLocalPort());
-			zlmrtpServerFactory.startSendRtpStream(mediaInfo, param);
-
+			param.put("pt", sendRtpItem.getPt());
+			param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0");
+			param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0");
+			JSONObject jsonObject = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param);
+			if (jsonObject == null) {
+				logger.error("RTP推流失败: 请检查ZLM服务");
+			} else if (jsonObject.getInteger("code") == 0) {
+				logger.info("RTP推流成功[ {}/{} ],{}->{}:{}, " ,param.get("app"), param.get("stream"), jsonObject.getString("local_port"), param.get("dst_url"), param.get("dst_port"));
+			} else {
+				logger.error("RTP推流失败: {}, 参数:{}",jsonObject.getString("msg"),JSONObject.toJSON(param));
+				if (sendRtpItem.isOnlyAudio()) {
+					// TODO 可能是语音对讲
+				}else {
+					// 向上级平台
+					commanderForPlatform.streamByeCmd(parentPlatform, callIdHeader.getCallId());
+				}
+			}
 
 
 //			if (streamInfo == null) { // 流还没上来,对方就回复ack

+ 0 - 12
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/PresetQueryResponseMessageHandler.java

@@ -1,22 +1,12 @@
 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd;
 
-import com.genersoft.iot.vmp.conf.SipConfig;
-import com.genersoft.iot.vmp.conf.UserSetting;
 import com.genersoft.iot.vmp.domain.req.PresetQuerySipReq;
 import com.genersoft.iot.vmp.gb28181.bean.*;
-import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
-import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
-import com.genersoft.iot.vmp.gb28181.session.CatalogDataCatch;
 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
-import com.genersoft.iot.vmp.gb28181.utils.Coordtransform;
-import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
-import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
-import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
-import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import org.dom4j.DocumentException;
 import org.dom4j.Element;
 import org.slf4j.Logger;
@@ -24,7 +14,6 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.InitializingBean;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
-import org.springframework.util.StringUtils;
 
 import javax.sip.InvalidArgumentException;
 import javax.sip.RequestEvent;
@@ -35,7 +24,6 @@ import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
-import java.util.UUID;
 
 import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
 

+ 1 - 11
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java

@@ -246,17 +246,7 @@ public class ZLMRTPServerFactory {
      * 调用zlm RESTFUL API —— startSendRtp
      */
     public JSONObject startSendRtpStream(MediaServerItem mediaServerItem, Map<String, Object>param) {
-        Boolean result = false;
-        JSONObject jsonObject = zlmresTfulUtils.startSendRtp(mediaServerItem, param);
-        if (jsonObject == null) {
-            logger.error("RTP推流失败: 请检查ZLM服务");
-        } else if (jsonObject.getInteger("code") == 0) {
-            result= true;
-            logger.info("RTP推流成功[ {}/{} ],{}->{}:{}, " ,param.get("app"), param.get("stream"), jsonObject.getString("local_port"), param.get("dst_url"), param.get("dst_port"));
-        } else {
-            logger.error("RTP推流失败: {}, 参数:{}",jsonObject.getString("msg"),JSONObject.toJSON(param));
-        }
-        return jsonObject;
+        return zlmresTfulUtils.startSendRtp(mediaServerItem, param);
     }
 
     /**