From c2aaae9325db012c9960b69784330ced5ec15ab9 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: 星期一, 09 五月 2022 18:15:30 +0800 Subject: [PATCH] 初步实现语音喊话 --- src/main/java/com/genersoft/iot/vmp/gb28181/bean/AudioBroadcastCatchStatus.java | 15 src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java | 17 - src/main/java/com/genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java | 3 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java | 81 +--- src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java | 2 src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java | 44 ++ src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/BroadcastResponseMessageHandler.java | 29 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/bean/AudioBroadcastEvent.java | 9 src/main/java/com/genersoft/iot/vmp/gb28181/session/AudioBroadcastManager.java | 59 +++ src/main/java/com/genersoft/iot/vmp/gb28181/bean/AudioBroadcastCatch.java | 59 +++ src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java | 3 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java | 15 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java | 188 +++++++++++ src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java | 6 web_src/src/components/dialog/deviceEdit.vue | 7 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItemLite.java | 197 ++++++++++++ src/main/java/com/genersoft/iot/vmp/vmanager/bean/AudioBroadcastResult.java | 62 +++ src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java | 118 +++--- src/main/java/com/genersoft/iot/vmp/service/IPlayService.java | 3 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageHandlerAbstract.java | 21 + 20 files changed, 760 insertions(+), 178 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/AudioBroadcastCatch.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/AudioBroadcastCatch.java new file mode 100644 index 0000000..64227d4 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/AudioBroadcastCatch.java @@ -0,0 +1,59 @@ +package com.genersoft.iot.vmp.gb28181.bean; + + +/** + * 缂撳瓨璇煶骞挎挱鐨勭姸鎬� + * @author lin + */ +public class AudioBroadcastCatch { + + + public AudioBroadcastCatch(String deviceId, String channelId, AudioBroadcastCatchStatus status) { + this.deviceId = deviceId; + this.channelId = channelId; + this.status = status; + } + + public AudioBroadcastCatch() { + } + + /** + * 璁惧缂栧彿 + */ + private String deviceId; + + /** + * 閫氶亾缂栧彿 + */ + private String channelId; + + /** + * 璇煶骞挎挱鐘舵�� + */ + private AudioBroadcastCatchStatus status; + + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getChannelId() { + return channelId; + } + + public void setChannelId(String channelId) { + this.channelId = channelId; + } + + public AudioBroadcastCatchStatus getStatus() { + return status; + } + + public void setStatus(AudioBroadcastCatchStatus status) { + this.status = status; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/AudioBroadcastCatchStatus.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/AudioBroadcastCatchStatus.java new file mode 100644 index 0000000..7d4f7c8 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/AudioBroadcastCatchStatus.java @@ -0,0 +1,15 @@ +package com.genersoft.iot.vmp.gb28181.bean; + +/** + * 璇煶骞挎挱鐘舵�� + * @author lin + */ +public enum AudioBroadcastCatchStatus { + + // 鍙戦�佽闊冲箍鎾秷鎭瓑寰呭鏂瑰洖澶嶈闊冲箍鎾� + Ready, + // 鏀跺埌鍥炲绛夊緟invite娑堟伅 + WaiteInvite, + // 鏀跺埌invite娑堟伅 + Ok, +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java index 778608e..1dc62ab 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java @@ -134,16 +134,6 @@ */ private boolean ssrcCheck; - /** - * 璁惧鐢ㄤ簬鎺ユ敹璇煶娑堟伅鐨勯�氶亾 - */ - private String audioChannelForReceive; - - /** - * 璁惧鐢ㄤ簬鍙戦�佽闊虫秷鎭殑閫氶亾 - */ - private String audioChannelForSend; - public String getDeviceId() { return deviceId; @@ -345,11 +335,4 @@ this.ssrcCheck = ssrcCheck; } - public String getAudioChannelForReceive() { - return audioChannelForReceive; - } - - public void setAudioChannelForReceive(String audioChannelForReceive) { - this.audioChannelForReceive = audioChannelForReceive; - } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/session/AudioBroadcastManager.java b/src/main/java/com/genersoft/iot/vmp/gb28181/session/AudioBroadcastManager.java new file mode 100644 index 0000000..dec96c0 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/session/AudioBroadcastManager.java @@ -0,0 +1,59 @@ +package com.genersoft.iot.vmp.gb28181.session; + +import com.genersoft.iot.vmp.gb28181.bean.AudioBroadcastCatch; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 璇煶骞挎挱娑堟伅绠$悊绫� + * @author lin + */ +@Component +public class AudioBroadcastManager { + + public static Map<String, AudioBroadcastCatch> data = new ConcurrentHashMap<>(); + + public void add(AudioBroadcastCatch audioBroadcastCatch) { + this.update(audioBroadcastCatch); + } + + public void update(AudioBroadcastCatch audioBroadcastCatch) { + data.put(audioBroadcastCatch.getDeviceId() + audioBroadcastCatch.getChannelId(), audioBroadcastCatch); + } + + public void del(String deviceId, String channelId) { + data.remove(deviceId + channelId); + } + + public void delByDeviceId(String deviceId) { + for (String key : data.keySet()) { + if (key.startsWith(deviceId)) { + data.remove(key); + } + } + } + + public List<AudioBroadcastCatch> getAll(){ + Collection<AudioBroadcastCatch> values = data.values(); + return new ArrayList<>(values); + } + + + public boolean exit(String deviceId, String channelId) { + for (String key : data.keySet()) { + if (key.equals(deviceId + channelId)) { + return true; + } + } + return false; + } + + public AudioBroadcastCatch get(String deviceId, String channelId) { + return data.get(deviceId + channelId); + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java b/src/main/java/com/genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java index 62393d5..3d53914 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java @@ -21,9 +21,6 @@ public static Map<String, CatalogData> data = new ConcurrentHashMap<>(); @Autowired - private DeferredResultHolder deferredResultHolder; - - @Autowired private IVideoManagerStorage storager; public void addReady(Device device, int sn ) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java index f4bcbb6..bd51cfa 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java @@ -6,8 +6,12 @@ import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.service.bean.SSRCInfo; +import gov.nist.javax.sip.message.SIPRequest; +import gov.nist.javax.sip.stack.SIPDialog; import javax.sip.Dialog; +import javax.sip.SipException; +import java.text.ParseException; /** * @description:璁惧鑳藉姏鎺ュ彛锛岀敤浜庡畾涔夎澶囩殑鎺у埗銆佹煡璇㈣兘鍔� @@ -123,6 +127,7 @@ */ void streamByeCmd(String deviceId, String channelId, String stream, String callId, SipSubscribe.Event okEvent); void streamByeCmd(String deviceId, String channelId, String stream, String callId); + void streamByeCmd(SIPDialog dialog, SIPRequest request, SipSubscribe.Event okEvent) throws SipException, ParseException; /** * 鍥炴斁鏆傚仠 @@ -144,21 +149,13 @@ */ void playSpeedCmd(Device device, StreamInfo streamInfo, Double speed); - /** - * 璇煶骞挎挱 - * - * @param device 瑙嗛璁惧 - * @param channelId 棰勮閫氶亾 - */ - boolean audioBroadcastCmd(Device device,String channelId); /** * 璇煶骞挎挱 * * @param device 瑙嗛璁惧 */ - void audioBroadcastCmd(Device device, SipSubscribe.Event okEvent); - boolean audioBroadcastCmd(Device device); + boolean audioBroadcastCmd(Device device, String channelId, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent); /** * 闊宠棰戝綍鍍忔帶鍒� 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 ea8f202..8ff1e45 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 @@ -733,42 +733,34 @@ } } - Request byeRequest = dialog.createRequest(Request.BYE); - SipURI byeURI = (SipURI) byeRequest.getRequestURI(); - SIPRequest request = (SIPRequest)transaction.getRequest(); - byeURI.setHost(request.getRemoteAddress().getHostAddress()); - byeURI.setPort(request.getRemotePort()); - ViaHeader viaHeader = (ViaHeader) byeRequest.getHeader(ViaHeader.NAME); - String protocol = viaHeader.getTransport().toUpperCase(); - ClientTransaction clientTransaction = null; - if("TCP".equals(protocol)) { - clientTransaction = tcpSipProvider.getNewClientTransaction(byeRequest); - } else if("UDP".equals(protocol)) { - clientTransaction = udpSipProvider.getNewClientTransaction(byeRequest); - } - - CallIdHeader callIdHeader = (CallIdHeader) byeRequest.getHeader(CallIdHeader.NAME); - if (okEvent != null) { - sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), okEvent); - } - - dialog.sendRequest(clientTransaction); + streamByeCmd(dialog, (SIPRequest)transaction.getRequest(), okEvent); } catch (SipException | ParseException e) { e.printStackTrace(); } } - /** - * 璇煶骞挎挱 - * - * @param device 瑙嗛璁惧 - * @param channelId 棰勮閫氶亾 - */ @Override - public boolean audioBroadcastCmd(Device device, String channelId) { - // 鏀逛负鏂扮殑瀹炵幇 - return false; + public void streamByeCmd(SIPDialog dialog, SIPRequest request, SipSubscribe.Event okEvent) throws SipException, ParseException { + Request byeRequest = dialog.createRequest(Request.BYE); + SipURI byeURI = (SipURI) byeRequest.getRequestURI(); + byeURI.setHost(request.getRemoteAddress().getHostAddress()); + byeURI.setPort(request.getRemotePort()); + ViaHeader viaHeader = (ViaHeader) byeRequest.getHeader(ViaHeader.NAME); + String protocol = viaHeader.getTransport().toUpperCase(); + ClientTransaction clientTransaction = null; + if("TCP".equals(protocol)) { + clientTransaction = tcpSipProvider.getNewClientTransaction(byeRequest); + } else if("UDP".equals(protocol)) { + clientTransaction = udpSipProvider.getNewClientTransaction(byeRequest); + } + + CallIdHeader callIdHeader = (CallIdHeader) byeRequest.getHeader(CallIdHeader.NAME); + if (okEvent != null) { + sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), okEvent); + } + + dialog.sendRequest(clientTransaction); } /** @@ -777,7 +769,7 @@ * @param device 瑙嗛璁惧 */ @Override - public boolean audioBroadcastCmd(Device device) { + public boolean audioBroadcastCmd(Device device,String channelId, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) { try { StringBuffer broadcastXml = new StringBuffer(200); String charset = device.getCharset(); @@ -786,7 +778,7 @@ broadcastXml.append("<CmdType>Broadcast</CmdType>\r\n"); broadcastXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); broadcastXml.append("<SourceID>" + sipConfig.getId() + "</SourceID>\r\n"); - broadcastXml.append("<TargetID>" + device.getDeviceId() + "</TargetID>\r\n"); + broadcastXml.append("<TargetID>" + channelId + "</TargetID>\r\n"); broadcastXml.append("</Notify>\r\n"); String tm = Long.toString(System.currentTimeMillis()); @@ -795,39 +787,14 @@ : udpSipProvider.getNewCallId(); Request request = headerProvider.createMessageRequest(device, broadcastXml.toString(), "z9hG4bK-ViaBcst-" + tm, "FromBcst" + tm, null, callIdHeader); - transmitRequest(device, request); + transmitRequest(device, request, errorEvent, okEvent); return true; } catch (SipException | ParseException | InvalidArgumentException e) { e.printStackTrace(); } return false; } - @Override - public void audioBroadcastCmd(Device device, SipSubscribe.Event errorEvent) { - try { - StringBuffer broadcastXml = new StringBuffer(200); - String charset = device.getCharset(); - broadcastXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); - broadcastXml.append("<Notify>\r\n"); - broadcastXml.append("<CmdType>Broadcast</CmdType>\r\n"); - broadcastXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); - broadcastXml.append("<SourceID>" + sipConfig.getId() + "</SourceID>\r\n"); - broadcastXml.append("<TargetID>" + device.getDeviceId() + "</TargetID>\r\n"); - broadcastXml.append("</Notify>\r\n"); - - String tm = Long.toString(System.currentTimeMillis()); - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() - : udpSipProvider.getNewCallId(); - - Request request = headerProvider.createMessageRequest(device, broadcastXml.toString(), "z9hG4bK-ViaBcst-" + tm, "FromBcst" + tm, null, callIdHeader); - transmitRequest(device, request, errorEvent); - } catch (SipException | ParseException | InvalidArgumentException e) { - e.printStackTrace(); - } - } - - /** * 闊宠棰戝綍鍍忔帶鍒� * diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java index 0f65bf5..5fd6c99 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java @@ -94,6 +94,9 @@ param.put("dst_port", sendRtpItem.getPort()); param.put("is_udp", is_Udp); param.put("src_port", sendRtpItem.getLocalPort()); + param.put("pt", 8); + param.put("use_ps", 0); + param.put("only_audio", 1); zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java index bb46a71..ae49e2c 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java @@ -2,21 +2,27 @@ import com.alibaba.fastjson.JSONObject; import com.genersoft.iot.vmp.conf.DynamicTask; +import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; +import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; +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.ISIPCommander; 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.event.request.ISIPRequestProcessor; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; import com.genersoft.iot.vmp.gb28181.utils.SipUtils; +import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager; import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItemLite; import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.IPlayService; import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; @@ -24,8 +30,12 @@ import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.utils.SerializeUtils; +import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; +import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import gov.nist.javax.sdp.TimeDescriptionImpl; import gov.nist.javax.sdp.fields.TimeField; +import gov.nist.javax.sip.message.SIPRequest; +import gov.nist.javax.sip.stack.SIPDialog; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; @@ -41,6 +51,7 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.List; import java.util.Vector; /** @@ -73,7 +84,7 @@ private IPlayService playService; @Autowired - private ISIPCommander commander; + private AudioBroadcastManager audioBroadcastManager; @Autowired private ZLMRTPServerFactory zlmrtpServerFactory; @@ -92,6 +103,15 @@ @Autowired private ZLMMediaListManager mediaListManager; + + @Autowired + private DeferredResultHolder resultHolder; + + @Autowired + private ZLMHttpHookSubscribe subscribe; + + @Autowired + private SipConfig config; @Override @@ -126,7 +146,7 @@ // 鏌ヨ璇锋眰鏄惁鏉ヨ嚜涓婄骇骞冲彴\璁惧 ParentPlatform platform = storager.queryParentPlatByServerGBId(requesterId); if (platform == null) { - inviteFromDeviceHandle(evt, requesterId); + inviteFromDeviceHandle(evt, requesterId, channelId); }else { // 鏌ヨ骞冲彴涓嬫槸鍚︽湁璇ラ�氶亾 DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId); @@ -542,10 +562,25 @@ } } - public void inviteFromDeviceHandle(RequestEvent evt, String requesterId) throws InvalidArgumentException, ParseException, SipException, SdpException { + public void inviteFromDeviceHandle(RequestEvent evt, String requesterId, String channelId) throws InvalidArgumentException, ParseException, SipException, SdpException { + // 鍏煎濂囪懇鐨勬捣搴疯繖閲屼娇鐢ㄧ殑涓嶆槸閫氶亾缂栧彿鑰屾槸鏈钩鍙扮紪鍙� +// if (channelId.equals(config.getId())) { +// List<AudioBroadcastCatch> all = audioBroadcastManager.getAll(); +// for (AudioBroadcastCatch audioBroadcastCatch : all) { +// if (audioBroadcastCatch.getDeviceId().equals(requesterId)) { +// channelId = audioBroadcastCatch.getChannelId(); +// } +// } +// } +// // 鍏煎澶辫触 +// if (channelId.equals(config.getId())) { +// responseAck(evt, Response.BAD_REQUEST); +// return; +// } // 闈炰笂绾у钩鍙拌姹傦紝鏌ヨ鏄惁璁惧璇锋眰锛堥�氬父涓烘帴鏀惰闊冲箍鎾殑璁惧锛� Device device = redisCatchStorage.getDevice(requesterId); + Request request = evt.getRequest(); if (device != null) { logger.info("鏀跺埌璁惧" + requesterId + "鐨勮闊冲箍鎾璉nvite璇锋眰"); @@ -558,7 +593,7 @@ int ssrcIndex = contentString.indexOf("y="); if (ssrcIndex > 0) { substring = contentString.substring(0, ssrcIndex); - ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); + ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12).trim(); } ssrcIndex = substring.indexOf("f="); if (ssrcIndex > 0) { @@ -568,6 +603,7 @@ // 鑾峰彇鏀寔鐨勬牸寮� Vector mediaDescriptions = sdp.getMediaDescriptions(true); + // 鏌ョ湅鏄惁鏀寔PS 璐熻浇96 int port = -1; //boolean recvonly = false; @@ -602,10 +638,150 @@ responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 涓嶆敮鎸佺殑鏍煎紡锛屽彂415 return; } - String username = sdp.getOrigin().getUsername(); + String sessionName = sdp.getSessionName().getValue(); String addressStr = sdp.getOrigin().getAddress(); - logger.info("璁惧{}璇锋眰璇煶娴侊紝鍦板潃锛歿}:{}锛宻src锛歿}", username, addressStr, port, ssrc); + logger.info("璁惧{}璇锋眰璇煶娴侊紝鍦板潃锛歿}:{}锛宻src锛歿}", requesterId, addressStr, port, ssrc); + MediaServerItem mediaServerItem = playService.getNewMediaServerItem(device); + if (mediaServerItem == null) { + logger.warn("鏈壘鍒板彲鐢ㄧ殑zlm"); + responseAck(evt, Response.BUSY_HERE); + return; + } + SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, + device.getDeviceId(), channelId, + mediaTransmissionTCP); + sendRtpItem.setTcp(mediaTransmissionTCP); + if (tcpActive != null) { + sendRtpItem.setTcpActive(tcpActive); + } + if (sendRtpItem == null) { + logger.warn("鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�"); + responseAck(evt, Response.BUSY_HERE); + return; + } + + String app = "broadcast"; + String stream = device.getDeviceId() + "_" + channelId; + + CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME); + sendRtpItem.setPlayType(InviteStreamType.PLAY); + sendRtpItem.setCallId(callIdHeader.getCallId()); + sendRtpItem.setPlatformId(requesterId); + sendRtpItem.setStatus(1); + sendRtpItem.setApp(app); + sendRtpItem.setStreamId(stream); + redisCatchStorage.updateSendRTPSever(sendRtpItem); + + // hook鐩戝惉绛夊緟璁惧鎺ㄦ祦涓婃潵 + // 娣诲姞璁㈤槄 + JSONObject subscribeKey = new JSONObject(); + subscribeKey.put("app", app); + subscribeKey.put("stream", stream); + subscribeKey.put("regist", true); + subscribeKey.put("schema", "rtmp"); + subscribeKey.put("mediaServerId", mediaServerItem.getId()); + String finalSsrc = ssrc; + String waiteStreamTimeoutTaskKey = "waite-stream-" + device.getDeviceId() + channelId; + if (zlmrtpServerFactory.isStreamReady(mediaServerItem, app, stream)) { + logger.info("鍙戠幇宸茬粡鍦ㄦ帹娴�"); + dynamicTask.stop(waiteStreamTimeoutTaskKey); + sendRtpItem.setStatus(2); + redisCatchStorage.updateSendRTPSever(sendRtpItem); + StringBuffer content = new StringBuffer(200); + content.append("v=0\r\n"); + content.append("o="+ config.getId() +" "+ sdp.getOrigin().getSessionId() +" " + sdp.getOrigin().getSessionVersion() + " IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); + content.append("s=Play\r\n"); + content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); + content.append("t=0 0\r\n"); + content.append("m=audio "+ sendRtpItem.getLocalPort()+" RTP/AVP 8\r\n"); + content.append("a=sendonly\r\n"); + content.append("a=rtpmap:8 PCMA/8000\r\n"); + content.append("y="+ finalSsrc + "\r\n"); + content.append("f=v/////a/1/8/1\r\n"); + + ParentPlatform parentPlatform = new ParentPlatform(); + parentPlatform.setServerIP(device.getIp()); + parentPlatform.setServerPort(device.getPort()); + parentPlatform.setServerGBId(device.getDeviceId()); + try { + responseSdpAck(evt, content.toString(), parentPlatform); + } catch (SipException e) { + throw new RuntimeException(e); + } catch (InvalidArgumentException e) { + throw new RuntimeException(e); + } catch (ParseException e) { + throw new RuntimeException(e); + } + }else { + // 璁剧疆绛夊緟鎺ㄦ祦鐨勮秴鏃�; 榛樿20s + String finalChannelId = channelId; + dynamicTask.startDelay(waiteStreamTimeoutTaskKey, ()->{ + logger.info("绛夊緟鎺ㄦ祦瓒呮椂: {}/{}", app, stream); + if (audioBroadcastManager.exit(device.getDeviceId(), finalChannelId)) { + audioBroadcastManager.del(device.getDeviceId(), finalChannelId); + }else { + // 鍏煎娴峰悍浣跨敤浜嗛敊璇殑閫氶亾ID鐨勬儏鍐� + audioBroadcastManager.delByDeviceId(device.getDeviceId()); + } + + // 鍙戦�乥ye + try { + cmder.streamByeCmd((SIPDialog)evt.getServerTransaction().getDialog(), (SIPRequest) evt.getRequest(), null); + } catch (SipException e) { + throw new RuntimeException(e); + } catch (ParseException e) { + throw new RuntimeException(e); + } + }, 20*1000); + + subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, + (MediaServerItem mediaServerItemInUse, JSONObject json)->{ + sendRtpItem.setStatus(2); + redisCatchStorage.updateSendRTPSever(sendRtpItem); + StringBuffer content = new StringBuffer(200); + content.append("v=0\r\n"); + content.append("o="+ finalChannelId +" 0 0 IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); + content.append("s=Play\r\n"); + content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); + content.append("t=0 0\r\n"); + content.append("m=video "+ sendRtpItem.getLocalPort()+" RTP/AVP 8\r\n"); + content.append("a=sendonly\r\n"); + content.append("a=rtpmap:8 PCMA/8000\r\n"); + content.append("y="+ finalSsrc + "\r\n"); + content.append("f=v/////a/1/8/1\r\n"); + + ParentPlatform parentPlatform = new ParentPlatform(); + parentPlatform.setServerIP(device.getIp()); + parentPlatform.setServerPort(device.getPort()); + parentPlatform.setServerGBId(device.getDeviceId()); + try { + responseSdpAck(evt, content.toString(), parentPlatform); + } catch (SipException e) { + throw new RuntimeException(e); + } catch (InvalidArgumentException e) { + throw new RuntimeException(e); + } catch (ParseException e) { + throw new RuntimeException(e); + } + }); + } + String timeOutTaskKey = "audio-broadcast-" + device.getDeviceId() + channelId; + dynamicTask.stop(timeOutTaskKey); + String key = DeferredResultHolder.CALLBACK_CMD_BROADCAST + device.getDeviceId(); + WVPResult<AudioBroadcastResult> wvpResult = new WVPResult<>(); + wvpResult.setCode(0); + wvpResult.setMsg("success"); + AudioBroadcastResult audioBroadcastResult = new AudioBroadcastResult(); + audioBroadcastResult.setApp(app); + audioBroadcastResult.setStream(stream); + audioBroadcastResult.setMediaServerItem(new MediaServerItemLite(mediaServerItem)); + audioBroadcastResult.setCodec("G.711"); + wvpResult.setData(audioBroadcastResult); + RequestMessage requestMessage = new RequestMessage(); + requestMessage.setKey(key); + requestMessage.setData(wvpResult); + resultHolder.invokeAllResult(requestMessage); } else { logger.warn("鏉ヨ嚜鏃犳晥璁惧/骞冲彴鐨勮姹�"); responseAck(evt, Response.BAD_REQUEST); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageHandlerAbstract.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageHandlerAbstract.java index afaa7cb..cf7d112 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageHandlerAbstract.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageHandlerAbstract.java @@ -6,7 +6,11 @@ import org.dom4j.Element; import org.springframework.beans.factory.annotation.Autowired; +import javax.sip.InvalidArgumentException; import javax.sip.RequestEvent; +import javax.sip.SipException; +import javax.sip.message.Response; +import java.text.ParseException; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -23,6 +27,10 @@ @Override public void handForDevice(RequestEvent evt, Device device, Element element) { String cmd = getText(element, "CmdType"); + if (cmd == null) { + handNullCmd(evt); + return; + } IMessageHandler messageHandler = messageHandlerMap.get(cmd); if (messageHandler != null) { messageHandler.handForDevice(evt, device, element); @@ -37,4 +45,17 @@ messageHandler.handForPlatform(evt, parentPlatform, element); } } + + public void handNullCmd(RequestEvent evt){ + try { + responseAck(evt, Response.OK); + } catch (SipException e) { + throw new RuntimeException(e); + } catch (InvalidArgumentException e) { + throw new RuntimeException(e); + } catch (ParseException e) { + throw new RuntimeException(e); + } + return; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/BroadcastResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/BroadcastResponseMessageHandler.java index ac94655..e684be3 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/BroadcastResponseMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/BroadcastResponseMessageHandler.java @@ -1,8 +1,11 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd; import com.alibaba.fastjson.JSONObject; +import com.genersoft.iot.vmp.gb28181.bean.AudioBroadcastCatch; +import com.genersoft.iot.vmp.gb28181.bean.AudioBroadcastCatchStatus; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; +import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; 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; @@ -36,6 +39,9 @@ @Autowired private DeferredResultHolder deferredResultHolder; + @Autowired + private AudioBroadcastManager audioBroadcastManager; + @Override public void afterPropertiesSet() throws Exception { responseMessageHandler.addHandler(cmdType, this); @@ -45,21 +51,16 @@ public void handForDevice(RequestEvent evt, Device device, Element rootElement) { try { String channelId = getText(rootElement, "DeviceID"); - String key = DeferredResultHolder.CALLBACK_CMD_BROADCAST + device.getDeviceId() + channelId; - // 鍥炲200 OK - responseAck(evt, Response.OK); - // 姝ゅ鏄鏈钩鍙板彂鍑築roadcast鎸囦护鐨勫簲绛� - JSONObject json = new JSONObject(); - XmlUtil.node2Json(rootElement, json); - if (logger.isDebugEnabled()) { - logger.debug(json.toJSONString()); + if (!audioBroadcastManager.exit(device.getDeviceId(), channelId)) { + // 鍥炲410 + responseAck(evt, Response.GONE); + return; } - RequestMessage msg = new RequestMessage(); - msg.setKey(key); - msg.setData(json); - deferredResultHolder.invokeAllResult(msg); - - + logger.info("鏀跺埌璇煶骞挎挱鐨勫洖澶嶏細{}/{}", device.getDeviceId(), channelId ); + AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(device.getDeviceId(), channelId); + audioBroadcastCatch.setStatus(AudioBroadcastCatchStatus.WaiteInvite); + audioBroadcastManager.update(audioBroadcastCatch); + responseAck(evt, Response.OK); } catch (ParseException | SipException | InvalidArgumentException e) { e.printStackTrace(); } 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 a7e6016..5ab8044 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 @@ -271,7 +271,7 @@ * 鏌ヨ寰呰浆鎺ㄧ殑娴佹槸鍚﹀氨缁� */ public Boolean isStreamReady(MediaServerItem mediaServerItem, String app, String streamId) { - JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtmp", streamId); + JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtsp", streamId); return (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online")); } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItemLite.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItemLite.java new file mode 100644 index 0000000..de68e30 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItemLite.java @@ -0,0 +1,197 @@ +package com.genersoft.iot.vmp.media.zlm.dto; + + +import com.genersoft.iot.vmp.gb28181.session.SsrcConfig; +import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; +import org.springframework.util.StringUtils; + +import java.util.HashMap; + +/** + * 绮剧畝鐨凪ediaServerItem淇℃伅锛屾柟渚跨粰鍓嶇杩斿洖鏁版嵁 + */ +public class MediaServerItemLite { + + private String id; + + private String ip; + + private String hookIp; + + private String sdpIp; + + private String streamIp; + + private int httpPort; + + private int httpSSlPort; + + private int rtmpPort; + + private int rtmpSSlPort; + + private int rtpProxyPort; + + private int rtspPort; + + private int rtspSSLPort; + + private String secret; + + private int streamNoneReaderDelayMS; + + private int hookAliveInterval; + + private int recordAssistPort; + + + + public MediaServerItemLite(MediaServerItem mediaServerItem) { + this.id = mediaServerItem.getId(); + this.ip = mediaServerItem.getIp(); + this.hookIp = mediaServerItem.getHookIp(); + this.sdpIp = mediaServerItem.getSdpIp(); + this.streamIp = mediaServerItem.getStreamIp(); + this.httpPort = mediaServerItem.getHttpPort(); + this.httpSSlPort = mediaServerItem.getHttpSSlPort(); + this.rtmpPort = mediaServerItem.getRtmpPort(); + this.rtmpSSlPort = mediaServerItem.getRtmpSSlPort(); + this.rtpProxyPort = mediaServerItem.getRtpProxyPort(); + this.rtspPort = mediaServerItem.getRtspPort(); + this.rtspSSLPort = mediaServerItem.getRtspSSLPort(); + this.secret = mediaServerItem.getSecret(); + this.streamNoneReaderDelayMS = mediaServerItem.getStreamNoneReaderDelayMS(); + this.hookAliveInterval = mediaServerItem.getHookAliveInterval(); + this.streamNoneReaderDelayMS = mediaServerItem.getStreamNoneReaderDelayMS(); + this.recordAssistPort = mediaServerItem.getRecordAssistPort(); + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public String getHookIp() { + return hookIp; + } + + public void setHookIp(String hookIp) { + this.hookIp = hookIp; + } + + public String getSdpIp() { + return sdpIp; + } + + public void setSdpIp(String sdpIp) { + this.sdpIp = sdpIp; + } + + public String getStreamIp() { + return streamIp; + } + + public void setStreamIp(String streamIp) { + this.streamIp = streamIp; + } + + public int getHttpPort() { + return httpPort; + } + + public void setHttpPort(int httpPort) { + this.httpPort = httpPort; + } + + public int getHttpSSlPort() { + return httpSSlPort; + } + + public void setHttpSSlPort(int httpSSlPort) { + this.httpSSlPort = httpSSlPort; + } + + public int getRtmpPort() { + return rtmpPort; + } + + public void setRtmpPort(int rtmpPort) { + this.rtmpPort = rtmpPort; + } + + public int getRtmpSSlPort() { + return rtmpSSlPort; + } + + public void setRtmpSSlPort(int rtmpSSlPort) { + this.rtmpSSlPort = rtmpSSlPort; + } + + public int getRtpProxyPort() { + return rtpProxyPort; + } + + public void setRtpProxyPort(int rtpProxyPort) { + this.rtpProxyPort = rtpProxyPort; + } + + public int getRtspPort() { + return rtspPort; + } + + public void setRtspPort(int rtspPort) { + this.rtspPort = rtspPort; + } + + public int getRtspSSLPort() { + return rtspSSLPort; + } + + public void setRtspSSLPort(int rtspSSLPort) { + this.rtspSSLPort = rtspSSLPort; + } + + + public String getSecret() { + return secret; + } + + public void setSecret(String secret) { + this.secret = secret; + } + + public int getStreamNoneReaderDelayMS() { + return streamNoneReaderDelayMS; + } + + public void setStreamNoneReaderDelayMS(int streamNoneReaderDelayMS) { + this.streamNoneReaderDelayMS = streamNoneReaderDelayMS; + } + + public int getHookAliveInterval() { + return hookAliveInterval; + } + + public void setHookAliveInterval(int hookAliveInterval) { + this.hookAliveInterval = hookAliveInterval; + } + + public int getRecordAssistPort() { + return recordAssistPort; + } + + public void setRecordAssistPort(int recordAssistPort) { + this.recordAssistPort = recordAssistPort; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java b/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java index 9e76493..6300551 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java @@ -11,6 +11,7 @@ import com.genersoft.iot.vmp.service.bean.InviteTimeOutCallback; import com.genersoft.iot.vmp.service.bean.PlayBackCallback; import com.genersoft.iot.vmp.service.bean.SSRCInfo; +import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent; import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; import org.springframework.http.ResponseEntity; import org.springframework.web.context.request.async.DeferredResult; @@ -40,4 +41,6 @@ DeferredResult<ResponseEntity<String>> download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack); StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream); + + void audioBroadcast(Device device, String channelId, int timeout, AudioBroadcastEvent event); } 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 f2b6c28..a647c84 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 @@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; +import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; 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; @@ -26,7 +27,9 @@ import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.utils.redis.RedisUtil; +import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; import com.genersoft.iot.vmp.vmanager.bean.WVPResult; +import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent; import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; import com.genersoft.iot.vmp.service.IMediaService; import com.genersoft.iot.vmp.service.IPlayService; @@ -56,6 +59,9 @@ @Autowired private SIPCommander cmder; + + @Autowired + private AudioBroadcastManager audioBroadcastManager; @Autowired private SIPCommanderFroPlatform sipCommanderFroPlatform; @@ -621,4 +627,42 @@ } } } + + @Override + public void audioBroadcast(Device device, String channelId, int timeout, AudioBroadcastEvent event) { + if (device == null || channelId == null) { + return; + } + DeviceChannel deviceChannel = storager.queryChannel(device.getDeviceId(), channelId); + if (deviceChannel == null) { + logger.warn("寮�鍚闊冲箍鎾殑鏃跺�欐湭鎵惧埌閫氶亾锛� {}", channelId); + event.call("寮�鍚闊冲箍鎾殑鏃跺�欐湭鎵惧埌閫氶亾"); + return; + } + // 鏌ヨ閫氶亾浣跨敤鐘舵�� + if (audioBroadcastManager.exit(device.getDeviceId(), channelId)) { + logger.warn("璇煶骞挎挱宸茬粡寮�鍚細 {}", channelId); + event.call("璇煶骞挎挱宸茬粡寮�鍚�"); + return; + } + String timeOutTaskKey = "audio-broadcast-" + device.getDeviceId() + channelId; + dynamicTask.startDelay(timeOutTaskKey, ()->{ + logger.error("璇煶骞挎挱鍙戦�佽秴鏃讹細 {}:{}", device.getDeviceId(), channelId); + event.call("璇煶骞挎挱鍙戦�佽秴鏃�"); + audioBroadcastManager.del(device.getDeviceId(), channelId); + }, timeout * 1000); + + // 鍙戦�侀�氱煡 + cmder.audioBroadcastCmd(device, channelId, eventResultForOk -> { + // 鍙戦�佹垚鍔� + AudioBroadcastCatch audioBroadcastCatch = new AudioBroadcastCatch(device.getDeviceId(), channelId, AudioBroadcastCatchStatus.Ready); + audioBroadcastManager.add(audioBroadcastCatch); + }, eventResultForError -> { + dynamicTask.stop(timeOutTaskKey); + // 鍙戦�佸け璐� + logger.error("璇煶骞挎挱鍙戦�佸け璐ワ細 {}:{}", channelId, eventResultForError.msg); + event.call("璇煶骞挎挱鍙戦�佸け璐�"); + audioBroadcastManager.del(device.getDeviceId(), channelId); + }); + } } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java index d1c942f..97cf2cc 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java @@ -37,8 +37,6 @@ "subscribeCycleForMobilePosition," + "mobilePositionSubmissionInterval," + "subscribeCycleForAlarm," + - "audioChannelForReceive," + - "audioChannelForSend," + "ssrcCheck," + "online" + ") VALUES (" + @@ -62,8 +60,6 @@ "#{subscribeCycleForMobilePosition}," + "#{mobilePositionSubmissionInterval}," + "#{subscribeCycleForAlarm}," + - "#{audioChannelForReceive}," + - "#{audioChannelForSend}," + "#{ssrcCheck}," + "#{online}" + ")") @@ -90,8 +86,6 @@ "<if test=\"subscribeCycleForMobilePosition != null\">, subscribeCycleForMobilePosition=${subscribeCycleForMobilePosition}</if>" + "<if test=\"mobilePositionSubmissionInterval != null\">, mobilePositionSubmissionInterval=${mobilePositionSubmissionInterval}</if>" + "<if test=\"subscribeCycleForAlarm != null\">, subscribeCycleForAlarm=${subscribeCycleForAlarm}</if>" + - "<if test=\"audioChannelForReceive != null\">, audioChannelForReceive=#{audioChannelForReceive}</if>" + - "<if test=\"audioChannelForSend != null\">, audioChannelForSend=#{audioChannelForSend}</if>" + "<if test=\"ssrcCheck != null\">, ssrcCheck=${ssrcCheck}</if>" + "WHERE deviceId='${deviceId}'"+ " </script>"}) diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/bean/AudioBroadcastResult.java b/src/main/java/com/genersoft/iot/vmp/vmanager/bean/AudioBroadcastResult.java new file mode 100644 index 0000000..a722ae8 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/bean/AudioBroadcastResult.java @@ -0,0 +1,62 @@ +package com.genersoft.iot.vmp.vmanager.bean; + +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItemLite; + +/** + * @author lin + */ +public class AudioBroadcastResult { + /** + * 鎺ㄦ祦鐨勫獟浣撹妭鐐逛俊鎭� + */ + private MediaServerItemLite mediaServerItem; + + /** + * 缂栫爜鏍煎紡 + */ + private String codec; + + /** + * 鍚憐lm鎺ㄦ祦鐨勫簲鐢ㄥ悕 + */ + private String app; + + /** + * 鍚憐lm鎺ㄦ祦鐨勬祦ID + */ + private String stream; + + + public MediaServerItemLite getMediaServerItem() { + return mediaServerItem; + } + + public void setMediaServerItem(MediaServerItemLite mediaServerItem) { + this.mediaServerItem = mediaServerItem; + } + + public String getCodec() { + return codec; + } + + public void setCodec(String codec) { + this.codec = codec; + } + + 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; + } +} 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 dc88da0..d587e0d 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 @@ -11,6 +11,7 @@ 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.vmanager.bean.AudioBroadcastResult; import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; import com.genersoft.iot.vmp.service.IMediaService; @@ -39,6 +40,9 @@ import java.util.List; import java.util.UUID; +/** + * @author lin + */ @Api(tags = "鍥芥爣璁惧鐐规挱") @CrossOrigin @RestController @@ -102,7 +106,7 @@ logger.debug(String.format("璁惧棰勮/鍥炴斁鍋滄API璋冪敤锛宻treamId锛�%s_%s", deviceId, channelId )); String uuid = UUID.randomUUID().toString(); - DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(); + DeferredResult<ResponseEntity<String>> result = new DeferredResult<>(); // 褰曞儚鏌ヨ浠hannelId浣滀负deviceId鏌ヨ String key = DeferredResultHolder.CALLBACK_CMD_STOP + deviceId + channelId; @@ -123,7 +127,7 @@ RequestMessage msgForSuccess = new RequestMessage(); msgForSuccess.setId(uuid); msgForSuccess.setKey(key); - msgForSuccess.setData(String.format("success")); + msgForSuccess.setData("success"); resultHolder.invokeAllResult(msgForSuccess); }); @@ -251,81 +255,73 @@ @ApiOperation("璇煶骞挎挱鍛戒护") @ApiImplicitParams({ @ApiImplicitParam(name = "deviceId", value = "璁惧Id", dataTypeClass = String.class), - @ApiImplicitParam(name = "channelForSend", value = "璁惧鐢ㄤ簬鍙戦�佽闊虫暟鎹殑閫氶亾", dataTypeClass = String.class), - @ApiImplicitParam(name = "channelForReceive", value = "璁惧鐢ㄤ簬鎺ユ敹璇煶鏁版嵁鐨勯�氶亾", dataTypeClass = String.class), + @ApiImplicitParam(name = "channelId", value = "閫氶亾Id", dataTypeClass = String.class), + @ApiImplicitParam(name = "timeout", value = "鎺ㄦ祦瓒呮椂鏃堕棿(绉�)", dataTypeClass = Integer.class), }) - @GetMapping("/broadcast/{deviceId}") - @PostMapping("/broadcast/{deviceId}") - public DeferredResult<ResponseEntity<String>> broadcastApi(@PathVariable String deviceId, - String channelForSend, - String channelForReceive) { + @GetMapping("/broadcast/{deviceId}/{channelId}") + @PostMapping("/broadcast/{deviceId}/{channelId}") + public DeferredResult<WVPResult<AudioBroadcastResult>> broadcastApi(@PathVariable String deviceId, @PathVariable String channelId, Integer timeout) { if (logger.isDebugEnabled()) { logger.debug("璇煶骞挎挱API璋冪敤"); } Device device = storager.queryVideoDevice(deviceId); - DeferredResult<ResponseEntity<String>> result = new DeferredResult<>(3 * 1000L); - String key = DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId; + if (device == null) { + WVPResult<AudioBroadcastResult> result = new WVPResult<>(); + result.setCode(-1); + result.setMsg("鏈壘鍒拌澶囷細 " + deviceId); + DeferredResult<WVPResult<AudioBroadcastResult>> deferredResult = new DeferredResult<>(); + deferredResult.setResult(result); + return deferredResult; + } + if (channelId == null) { + WVPResult<AudioBroadcastResult> result = new WVPResult<>(); + result.setCode(-1); + result.setMsg("鏈壘鍒伴�氶亾锛� " + channelId); + DeferredResult<WVPResult<AudioBroadcastResult>> deferredResult = new DeferredResult<>(); + deferredResult.setResult(result); + return deferredResult; + } + + String key = DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId; if (resultHolder.exist(key, null)) { - result.setResult(new ResponseEntity<>("璁惧浣跨敤涓�",HttpStatus.OK)); - return result; + WVPResult<AudioBroadcastResult> wvpResult = new WVPResult<>(); + wvpResult.setCode(-1); + wvpResult.setMsg("璁惧浣跨敤涓�"); + DeferredResult<WVPResult<AudioBroadcastResult>> deferredResult = new DeferredResult<>(); + deferredResult.setResult(wvpResult); + return deferredResult; } - -// playService.audioBroadcast(deviceId, channelForSend, channelForReceive); - - - - - - + if (timeout == null){ + timeout = 30; + } + DeferredResult<WVPResult<AudioBroadcastResult>> result = new DeferredResult<>(timeout.longValue()*1000 + 2000); String uuid = UUID.randomUUID().toString(); - if (device == null) { - - resultHolder.put(key, key, result); - RequestMessage msg = new RequestMessage(); - msg.setKey(key); - msg.setId(uuid); - JSONObject json = new JSONObject(); - json.put("DeviceID", deviceId); - json.put("CmdType", "Broadcast"); - json.put("Result", "Failed"); - json.put("Description", "Device 涓嶅瓨鍦�"); - msg.setData(json); - resultHolder.invokeResult(msg); - return result; - } - cmder.audioBroadcastCmd(device, (event) -> { - RequestMessage msg = new RequestMessage(); - msg.setKey(key); - msg.setId(uuid); - JSONObject json = new JSONObject(); - json.put("DeviceID", deviceId); - json.put("CmdType", "Broadcast"); - json.put("Result", "Failed"); - json.put("Description", String.format("璇煶骞挎挱鎿嶄綔澶辫触锛岄敊璇爜锛� %s, %s", event.statusCode, event.msg)); - msg.setData(json); - resultHolder.invokeResult(msg); + result.onTimeout(()->{ + WVPResult<AudioBroadcastResult> wvpResult = new WVPResult<>(); + wvpResult.setCode(-1); + wvpResult.setMsg("璇锋眰瓒呮椂"); + RequestMessage requestMessage = new RequestMessage(); + requestMessage.setKey(key); + requestMessage.setData(wvpResult); + resultHolder.invokeAllResult(requestMessage); }); - - result.onTimeout(() -> { - logger.warn(String.format("璇煶骞挎挱鎿嶄綔瓒呮椂, 璁惧鏈繑鍥炲簲绛旀寚浠�")); - RequestMessage msg = new RequestMessage(); - msg.setKey(key); - msg.setId(uuid); - JSONObject json = new JSONObject(); - json.put("DeviceID", deviceId); - json.put("CmdType", "Broadcast"); - json.put("Result", "Failed"); - json.put("Error", "Timeout. Device did not response to broadcast command."); - msg.setData(json); - resultHolder.invokeResult(msg); + playService.audioBroadcast(device, channelId, timeout, (msg)->{ + WVPResult<AudioBroadcastResult> wvpResult = new WVPResult<>(); + wvpResult.setCode(-1); + wvpResult.setMsg(msg); + RequestMessage requestMessage = new RequestMessage(); + requestMessage.setKey(key); + requestMessage.setData(wvpResult); + resultHolder.invokeAllResult(requestMessage); }); resultHolder.put(key, uuid, result); + return result; } @ApiOperation("鑾峰彇鎵�鏈夌殑ssrc") @GetMapping("/ssrc") - public WVPResult<JSONObject> getSSRC() { + public WVPResult<JSONObject> getSsrc() { if (logger.isDebugEnabled()) { logger.debug("鑾峰彇鎵�鏈夌殑ssrc"); } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/bean/AudioBroadcastEvent.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/bean/AudioBroadcastEvent.java new file mode 100644 index 0000000..55b710f --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/bean/AudioBroadcastEvent.java @@ -0,0 +1,9 @@ +package com.genersoft.iot.vmp.vmanager.gb28181.play.bean; + + +/** + * @author lin + */ +public interface AudioBroadcastEvent { + void call(String msg); +} diff --git a/web_src/src/components/dialog/deviceEdit.vue b/web_src/src/components/dialog/deviceEdit.vue index 745a3e6..7e4b3b2 100644 --- a/web_src/src/components/dialog/deviceEdit.vue +++ b/web_src/src/components/dialog/deviceEdit.vue @@ -37,9 +37,6 @@ </el-select> </el-form-item> <el-form-item label="璇煶鍙戦�侀�氶亾" prop="name"> - <el-input v-model="form.audioChannelForSend" clearable></el-input> - </el-form-item> - <el-form-item label="璇煶鎺ユ敹閫侀�氶亾" prop="name"> <el-input v-model="form.audioChannelForReceive" clearable></el-input> </el-form-item> <el-form-item label="鐩綍璁㈤槄" title="0涓哄彇娑堣闃�" prop="subscribeCycleForCatalog" > @@ -105,6 +102,8 @@ }) }, onSubmit: function () { + console.log("onSubmit"); + console.log(this.form); this.form.subscribeCycleForCatalog = this.form.subscribeCycleForCatalog||0 this.form.subscribeCycleForMobilePosition = this.form.subscribeCycleForMobilePosition||0 this.form.mobilePositionSubmissionInterval = this.form.mobilePositionSubmissionInterval||0 @@ -124,7 +123,7 @@ }); } }).catch(function (error) { - console.error(error); + console.log(error); }); }, close: function () { -- Gitblit v1.8.0