From ef742e715b8c0a983d661aa5b5f8980dade8c790 Mon Sep 17 00:00:00 2001
From: panlinlin <648540858@qq.com>
Date: 星期四, 22 四月 2021 15:28:40 +0800
Subject: [PATCH] 优化宕机后点播中设备发送bye

---
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java |   30 +++++++++++++++
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java        |   36 +++++++++++++++++-
 src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java                  |   17 ++++++++
 src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java                             |   17 ++++++++
 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java          |    1 
 5 files changed, 98 insertions(+), 3 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 6def294..1336d05 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
@@ -21,6 +21,15 @@
     private String rtc;
     private JSONArray tracks;
 
+    public static class TransactionInfo{
+        public String callId;
+        public String localTag;
+        public String remoteTag;
+        public String branch;
+    }
+
+    private TransactionInfo transactionInfo;
+
     public String getApp() {
         return app;
     }
@@ -148,4 +157,12 @@
     public void setRtc(String rtc) {
         this.rtc = rtc;
     }
+
+    public TransactionInfo getTransactionInfo() {
+        return transactionInfo;
+    }
+
+    public void setTransactionInfo(TransactionInfo transactionInfo) {
+        this.transactionInfo = transactionInfo;
+    }
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
index 14dd241..44bfc54 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
@@ -135,6 +135,36 @@
 		return request;
 	}
 
+	public Request createByteRequest(Device device, String channelId, String viaTag, String fromTag, String toTag, String callId) throws ParseException, InvalidArgumentException, PeerUnavailableException {
+		Request request = null;
+		//璇锋眰琛�
+		SipURI requestLine = sipFactory.createAddressFactory().createSipURI(channelId, device.getHostAddress());
+		// via
+		ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
+		ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(), device.getTransport(), viaTag);
+		viaHeaders.add(viaHeader);
+		//from
+		SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(),sipConfig.getSipDomain());
+		Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
+		FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag); //蹇呴』瑕佹湁鏍囪锛屽惁鍒欐棤娉曞垱寤轰細璇濓紝鏃犳硶鍥炲簲ack
+		//to
+		SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(channelId,sipConfig.getSipDomain());
+		Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
+		ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress,toTag);
+
+		//Forwards
+		MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
+
+		//ceq
+		CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(1L, Request.BYE);
+		CallIdHeader callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(callId);
+		request = sipFactory.createMessageFactory().createRequest(requestLine, Request.BYE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
+
+		Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(), sipConfig.getSipIp()+":"+sipConfig.getSipPort()));
+
+		return request;
+	}
+
 	public Request createSubscribeRequest(Device device, String content, String viaTag, String fromTag, String toTag, Integer expires, String event, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
 		Request request = null;
 		// sipuri
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 188676f..5f31d87 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
@@ -10,11 +10,14 @@
 import javax.sip.header.ViaHeader;
 import javax.sip.message.Request;
 
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.genersoft.iot.vmp.common.StreamInfo;
 import com.genersoft.iot.vmp.conf.MediaServerConfig;
 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
+import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
@@ -74,6 +77,9 @@
 
 	@Autowired
 	private ZLMRTPServerFactory zlmrtpServerFactory;
+
+	@Autowired
+	private ZLMRESTfulUtils zlmresTfulUtils;
 
 	@Value("${media.rtp.enable}")
 	private boolean rtpEnable;
@@ -577,13 +583,39 @@
 		
 		try {
 			ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId);
-			// 鏈嶅姟閲嶅惎鍚�
+			// 鏈嶅姟閲嶅惎鍚�, 鏃犳硶鐩存帴鍙戦�乥ye锛� 閫氳繃鎵嬪姩鏋勫缓鍙戦��
 			if (transaction == null) {
+
 				StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
 				if (streamInfo != null) {
+					JSONObject mediaList = zlmresTfulUtils.getMediaList(streamInfo.getApp(), streamInfo.getStreamId());
+					if (mediaList != null) { // 浠嶅湪鎺ㄦ祦鎵嶅彂閫�
+						if (mediaList.getInteger("code") == 0) {
+							JSONArray data = mediaList.getJSONArray("data");
+							if (data != null && data.size() > 0) {
+								Device device = storager.queryVideoDevice(deviceId);
+								if (device != null) {
+									StreamInfo.TransactionInfo transactionInfo = streamInfo.getTransactionInfo();
+									try {
+										Request byteRequest = headerProvider.createByteRequest(device, channelId,
+												transactionInfo.branch,
+												transactionInfo.localTag,
+												transactionInfo.remoteTag,
+												transactionInfo.callId);
+										transmitRequest(device, byteRequest);
+									} catch (InvalidArgumentException e) {
+										e.printStackTrace();
+									}
+								}
+							}
+						}
+					}
 					redisCatchStorage.stopPlay(streamInfo);
 				}
-				okEvent.response(null);
+
+				if (okEvent != null) {
+					okEvent.response(null);
+				}
 				return;
 			}
 			
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
index b4076d0..6022724 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -7,6 +7,7 @@
 import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
+import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
 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.cmd.impl.SIPCommander;
@@ -17,6 +18,7 @@
 import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
 import com.genersoft.iot.vmp.service.IMediaService;
 import com.genersoft.iot.vmp.service.IPlayService;
+import gov.nist.javax.sip.stack.SIPDialog;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -24,6 +26,9 @@
 import org.springframework.stereotype.Service;
 import org.springframework.web.context.request.async.DeferredResult;
 
+import javax.sip.ClientTransaction;
+import javax.sip.Dialog;
+import javax.sip.header.CallIdHeader;
 import javax.sip.message.Response;
 import java.util.UUID;
 
@@ -49,6 +54,9 @@
 
     @Autowired
     private IMediaService mediaService;
+
+    @Autowired
+    private VideoStreamSessionManager streamSession;
 
 
     @Override
@@ -141,7 +149,14 @@
                 deviceChannel.setStreamId(streamInfo.getStreamId());
                 storager.startPlay(deviceId, channelId, streamInfo.getStreamId());
             }
-
+            ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId);
+            SIPDialog dialog = (SIPDialog)transaction.getDialog();
+            StreamInfo.TransactionInfo transactionInfo = new StreamInfo.TransactionInfo();
+            transactionInfo.callId = dialog.getCallId().getCallId();
+            transactionInfo.localTag = dialog.getLocalTag();
+            transactionInfo.remoteTag = dialog.getRemoteTag();
+            transactionInfo.branch = dialog.getFirstTransactionInt().getBranchId();
+            streamInfo.setTransactionInfo(transactionInfo);
             redisCatchStorage.startPlay(streamInfo);
             msg.setData(JSON.toJSONString(streamInfo));
             resultHolder.invokeResult(msg);
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
index 3d4c64c..0685fb7 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
@@ -102,6 +102,7 @@
 				msg.setId(DeferredResultHolder.CALLBACK_CMD_STOP + uuid);
 				msg.setData("鐐规挱鏈壘鍒�");
 				resultHolder.invokeResult(msg);
+				storager.stopPlay(deviceId, channelId);
 			}else {
 				redisCatchStorage.stopPlay(streamInfo);
 				storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());

--
Gitblit v1.8.0