Commit c2aaae9325db012c9960b69784330ced5ec15ab9
1 parent
9f0ef439
初步实现语音喊话
Showing
20 changed files
with
761 additions
and
179 deletions
src/main/java/com/genersoft/iot/vmp/gb28181/bean/AudioBroadcastCatch.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.gb28181.bean; | |
| 2 | + | |
| 3 | + | |
| 4 | +/** | |
| 5 | + * 缓存语音广播的状态 | |
| 6 | + * @author lin | |
| 7 | + */ | |
| 8 | +public class AudioBroadcastCatch { | |
| 9 | + | |
| 10 | + | |
| 11 | + public AudioBroadcastCatch(String deviceId, String channelId, AudioBroadcastCatchStatus status) { | |
| 12 | + this.deviceId = deviceId; | |
| 13 | + this.channelId = channelId; | |
| 14 | + this.status = status; | |
| 15 | + } | |
| 16 | + | |
| 17 | + public AudioBroadcastCatch() { | |
| 18 | + } | |
| 19 | + | |
| 20 | + /** | |
| 21 | + * 设备编号 | |
| 22 | + */ | |
| 23 | + private String deviceId; | |
| 24 | + | |
| 25 | + /** | |
| 26 | + * 通道编号 | |
| 27 | + */ | |
| 28 | + private String channelId; | |
| 29 | + | |
| 30 | + /** | |
| 31 | + * 语音广播状态 | |
| 32 | + */ | |
| 33 | + private AudioBroadcastCatchStatus status; | |
| 34 | + | |
| 35 | + | |
| 36 | + public String getDeviceId() { | |
| 37 | + return deviceId; | |
| 38 | + } | |
| 39 | + | |
| 40 | + public void setDeviceId(String deviceId) { | |
| 41 | + this.deviceId = deviceId; | |
| 42 | + } | |
| 43 | + | |
| 44 | + public String getChannelId() { | |
| 45 | + return channelId; | |
| 46 | + } | |
| 47 | + | |
| 48 | + public void setChannelId(String channelId) { | |
| 49 | + this.channelId = channelId; | |
| 50 | + } | |
| 51 | + | |
| 52 | + public AudioBroadcastCatchStatus getStatus() { | |
| 53 | + return status; | |
| 54 | + } | |
| 55 | + | |
| 56 | + public void setStatus(AudioBroadcastCatchStatus status) { | |
| 57 | + this.status = status; | |
| 58 | + } | |
| 59 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/AudioBroadcastCatchStatus.java
0 → 100644
src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
| ... | ... | @@ -134,16 +134,6 @@ public class Device { |
| 134 | 134 | */ |
| 135 | 135 | private boolean ssrcCheck; |
| 136 | 136 | |
| 137 | - /** | |
| 138 | - * 设备用于接收语音消息的通道 | |
| 139 | - */ | |
| 140 | - private String audioChannelForReceive; | |
| 141 | - | |
| 142 | - /** | |
| 143 | - * 设备用于发送语音消息的通道 | |
| 144 | - */ | |
| 145 | - private String audioChannelForSend; | |
| 146 | - | |
| 147 | 137 | |
| 148 | 138 | public String getDeviceId() { |
| 149 | 139 | return deviceId; |
| ... | ... | @@ -345,11 +335,4 @@ public class Device { |
| 345 | 335 | this.ssrcCheck = ssrcCheck; |
| 346 | 336 | } |
| 347 | 337 | |
| 348 | - public String getAudioChannelForReceive() { | |
| 349 | - return audioChannelForReceive; | |
| 350 | - } | |
| 351 | - | |
| 352 | - public void setAudioChannelForReceive(String audioChannelForReceive) { | |
| 353 | - this.audioChannelForReceive = audioChannelForReceive; | |
| 354 | - } | |
| 355 | 338 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/session/AudioBroadcastManager.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.gb28181.session; | |
| 2 | + | |
| 3 | +import com.genersoft.iot.vmp.gb28181.bean.AudioBroadcastCatch; | |
| 4 | +import org.springframework.stereotype.Component; | |
| 5 | + | |
| 6 | +import java.util.ArrayList; | |
| 7 | +import java.util.Collection; | |
| 8 | +import java.util.List; | |
| 9 | +import java.util.Map; | |
| 10 | +import java.util.concurrent.ConcurrentHashMap; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * 语音广播消息管理类 | |
| 14 | + * @author lin | |
| 15 | + */ | |
| 16 | +@Component | |
| 17 | +public class AudioBroadcastManager { | |
| 18 | + | |
| 19 | + public static Map<String, AudioBroadcastCatch> data = new ConcurrentHashMap<>(); | |
| 20 | + | |
| 21 | + public void add(AudioBroadcastCatch audioBroadcastCatch) { | |
| 22 | + this.update(audioBroadcastCatch); | |
| 23 | + } | |
| 24 | + | |
| 25 | + public void update(AudioBroadcastCatch audioBroadcastCatch) { | |
| 26 | + data.put(audioBroadcastCatch.getDeviceId() + audioBroadcastCatch.getChannelId(), audioBroadcastCatch); | |
| 27 | + } | |
| 28 | + | |
| 29 | + public void del(String deviceId, String channelId) { | |
| 30 | + data.remove(deviceId + channelId); | |
| 31 | + } | |
| 32 | + | |
| 33 | + public void delByDeviceId(String deviceId) { | |
| 34 | + for (String key : data.keySet()) { | |
| 35 | + if (key.startsWith(deviceId)) { | |
| 36 | + data.remove(key); | |
| 37 | + } | |
| 38 | + } | |
| 39 | + } | |
| 40 | + | |
| 41 | + public List<AudioBroadcastCatch> getAll(){ | |
| 42 | + Collection<AudioBroadcastCatch> values = data.values(); | |
| 43 | + return new ArrayList<>(values); | |
| 44 | + } | |
| 45 | + | |
| 46 | + | |
| 47 | + public boolean exit(String deviceId, String channelId) { | |
| 48 | + for (String key : data.keySet()) { | |
| 49 | + if (key.equals(deviceId + channelId)) { | |
| 50 | + return true; | |
| 51 | + } | |
| 52 | + } | |
| 53 | + return false; | |
| 54 | + } | |
| 55 | + | |
| 56 | + public AudioBroadcastCatch get(String deviceId, String channelId) { | |
| 57 | + return data.get(deviceId + channelId); | |
| 58 | + } | |
| 59 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java
| ... | ... | @@ -21,9 +21,6 @@ public class CatalogDataCatch { |
| 21 | 21 | public static Map<String, CatalogData> data = new ConcurrentHashMap<>(); |
| 22 | 22 | |
| 23 | 23 | @Autowired |
| 24 | - private DeferredResultHolder deferredResultHolder; | |
| 25 | - | |
| 26 | - @Autowired | |
| 27 | 24 | private IVideoManagerStorage storager; |
| 28 | 25 | |
| 29 | 26 | public void addReady(Device device, int sn ) { | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
| ... | ... | @@ -6,8 +6,12 @@ import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| 6 | 6 | import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; |
| 7 | 7 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 8 | 8 | import com.genersoft.iot.vmp.service.bean.SSRCInfo; |
| 9 | +import gov.nist.javax.sip.message.SIPRequest; | |
| 10 | +import gov.nist.javax.sip.stack.SIPDialog; | |
| 9 | 11 | |
| 10 | 12 | import javax.sip.Dialog; |
| 13 | +import javax.sip.SipException; | |
| 14 | +import java.text.ParseException; | |
| 11 | 15 | |
| 12 | 16 | /** |
| 13 | 17 | * @description:设备能力接口,用于定义设备的控制、查询能力 |
| ... | ... | @@ -123,6 +127,7 @@ public interface ISIPCommander { |
| 123 | 127 | */ |
| 124 | 128 | void streamByeCmd(String deviceId, String channelId, String stream, String callId, SipSubscribe.Event okEvent); |
| 125 | 129 | void streamByeCmd(String deviceId, String channelId, String stream, String callId); |
| 130 | + void streamByeCmd(SIPDialog dialog, SIPRequest request, SipSubscribe.Event okEvent) throws SipException, ParseException; | |
| 126 | 131 | |
| 127 | 132 | /** |
| 128 | 133 | * 回放暂停 |
| ... | ... | @@ -144,21 +149,13 @@ public interface ISIPCommander { |
| 144 | 149 | */ |
| 145 | 150 | void playSpeedCmd(Device device, StreamInfo streamInfo, Double speed); |
| 146 | 151 | |
| 147 | - /** | |
| 148 | - * 语音广播 | |
| 149 | - * | |
| 150 | - * @param device 视频设备 | |
| 151 | - * @param channelId 预览通道 | |
| 152 | - */ | |
| 153 | - boolean audioBroadcastCmd(Device device,String channelId); | |
| 154 | 152 | |
| 155 | 153 | /** |
| 156 | 154 | * 语音广播 |
| 157 | 155 | * |
| 158 | 156 | * @param device 视频设备 |
| 159 | 157 | */ |
| 160 | - void audioBroadcastCmd(Device device, SipSubscribe.Event okEvent); | |
| 161 | - boolean audioBroadcastCmd(Device device); | |
| 158 | + boolean audioBroadcastCmd(Device device, String channelId, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent); | |
| 162 | 159 | |
| 163 | 160 | /** |
| 164 | 161 | * 音视频录像控制 | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
| ... | ... | @@ -733,42 +733,34 @@ public class SIPCommander implements ISIPCommander { |
| 733 | 733 | } |
| 734 | 734 | } |
| 735 | 735 | |
| 736 | - Request byeRequest = dialog.createRequest(Request.BYE); | |
| 737 | - SipURI byeURI = (SipURI) byeRequest.getRequestURI(); | |
| 738 | - SIPRequest request = (SIPRequest)transaction.getRequest(); | |
| 739 | - byeURI.setHost(request.getRemoteAddress().getHostAddress()); | |
| 740 | - byeURI.setPort(request.getRemotePort()); | |
| 741 | - ViaHeader viaHeader = (ViaHeader) byeRequest.getHeader(ViaHeader.NAME); | |
| 742 | - String protocol = viaHeader.getTransport().toUpperCase(); | |
| 743 | - ClientTransaction clientTransaction = null; | |
| 744 | - if("TCP".equals(protocol)) { | |
| 745 | - clientTransaction = tcpSipProvider.getNewClientTransaction(byeRequest); | |
| 746 | - } else if("UDP".equals(protocol)) { | |
| 747 | - clientTransaction = udpSipProvider.getNewClientTransaction(byeRequest); | |
| 748 | - } | |
| 749 | - | |
| 750 | - CallIdHeader callIdHeader = (CallIdHeader) byeRequest.getHeader(CallIdHeader.NAME); | |
| 751 | - if (okEvent != null) { | |
| 752 | - sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), okEvent); | |
| 753 | - } | |
| 754 | - | |
| 755 | - dialog.sendRequest(clientTransaction); | |
| 736 | + streamByeCmd(dialog, (SIPRequest)transaction.getRequest(), okEvent); | |
| 756 | 737 | |
| 757 | 738 | } catch (SipException | ParseException e) { |
| 758 | 739 | e.printStackTrace(); |
| 759 | 740 | } |
| 760 | 741 | } |
| 761 | 742 | |
| 762 | - /** | |
| 763 | - * 语音广播 | |
| 764 | - * | |
| 765 | - * @param device 视频设备 | |
| 766 | - * @param channelId 预览通道 | |
| 767 | - */ | |
| 768 | 743 | @Override |
| 769 | - public boolean audioBroadcastCmd(Device device, String channelId) { | |
| 770 | - // 改为新的实现 | |
| 771 | - return false; | |
| 744 | + public void streamByeCmd(SIPDialog dialog, SIPRequest request, SipSubscribe.Event okEvent) throws SipException, ParseException { | |
| 745 | + Request byeRequest = dialog.createRequest(Request.BYE); | |
| 746 | + SipURI byeURI = (SipURI) byeRequest.getRequestURI(); | |
| 747 | + byeURI.setHost(request.getRemoteAddress().getHostAddress()); | |
| 748 | + byeURI.setPort(request.getRemotePort()); | |
| 749 | + ViaHeader viaHeader = (ViaHeader) byeRequest.getHeader(ViaHeader.NAME); | |
| 750 | + String protocol = viaHeader.getTransport().toUpperCase(); | |
| 751 | + ClientTransaction clientTransaction = null; | |
| 752 | + if("TCP".equals(protocol)) { | |
| 753 | + clientTransaction = tcpSipProvider.getNewClientTransaction(byeRequest); | |
| 754 | + } else if("UDP".equals(protocol)) { | |
| 755 | + clientTransaction = udpSipProvider.getNewClientTransaction(byeRequest); | |
| 756 | + } | |
| 757 | + | |
| 758 | + CallIdHeader callIdHeader = (CallIdHeader) byeRequest.getHeader(CallIdHeader.NAME); | |
| 759 | + if (okEvent != null) { | |
| 760 | + sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), okEvent); | |
| 761 | + } | |
| 762 | + | |
| 763 | + dialog.sendRequest(clientTransaction); | |
| 772 | 764 | } |
| 773 | 765 | |
| 774 | 766 | /** |
| ... | ... | @@ -777,7 +769,7 @@ public class SIPCommander implements ISIPCommander { |
| 777 | 769 | * @param device 视频设备 |
| 778 | 770 | */ |
| 779 | 771 | @Override |
| 780 | - public boolean audioBroadcastCmd(Device device) { | |
| 772 | + public boolean audioBroadcastCmd(Device device,String channelId, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) { | |
| 781 | 773 | try { |
| 782 | 774 | StringBuffer broadcastXml = new StringBuffer(200); |
| 783 | 775 | String charset = device.getCharset(); |
| ... | ... | @@ -786,7 +778,7 @@ public class SIPCommander implements ISIPCommander { |
| 786 | 778 | broadcastXml.append("<CmdType>Broadcast</CmdType>\r\n"); |
| 787 | 779 | broadcastXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); |
| 788 | 780 | broadcastXml.append("<SourceID>" + sipConfig.getId() + "</SourceID>\r\n"); |
| 789 | - broadcastXml.append("<TargetID>" + device.getDeviceId() + "</TargetID>\r\n"); | |
| 781 | + broadcastXml.append("<TargetID>" + channelId + "</TargetID>\r\n"); | |
| 790 | 782 | broadcastXml.append("</Notify>\r\n"); |
| 791 | 783 | |
| 792 | 784 | String tm = Long.toString(System.currentTimeMillis()); |
| ... | ... | @@ -795,39 +787,14 @@ public class SIPCommander implements ISIPCommander { |
| 795 | 787 | : udpSipProvider.getNewCallId(); |
| 796 | 788 | |
| 797 | 789 | Request request = headerProvider.createMessageRequest(device, broadcastXml.toString(), "z9hG4bK-ViaBcst-" + tm, "FromBcst" + tm, null, callIdHeader); |
| 798 | - transmitRequest(device, request); | |
| 790 | + transmitRequest(device, request, errorEvent, okEvent); | |
| 799 | 791 | return true; |
| 800 | 792 | } catch (SipException | ParseException | InvalidArgumentException e) { |
| 801 | 793 | e.printStackTrace(); |
| 802 | 794 | } |
| 803 | 795 | return false; |
| 804 | 796 | } |
| 805 | - @Override | |
| 806 | - public void audioBroadcastCmd(Device device, SipSubscribe.Event errorEvent) { | |
| 807 | - try { | |
| 808 | - StringBuffer broadcastXml = new StringBuffer(200); | |
| 809 | - String charset = device.getCharset(); | |
| 810 | - broadcastXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); | |
| 811 | - broadcastXml.append("<Notify>\r\n"); | |
| 812 | - broadcastXml.append("<CmdType>Broadcast</CmdType>\r\n"); | |
| 813 | - broadcastXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); | |
| 814 | - broadcastXml.append("<SourceID>" + sipConfig.getId() + "</SourceID>\r\n"); | |
| 815 | - broadcastXml.append("<TargetID>" + device.getDeviceId() + "</TargetID>\r\n"); | |
| 816 | - broadcastXml.append("</Notify>\r\n"); | |
| 817 | - | |
| 818 | - String tm = Long.toString(System.currentTimeMillis()); | |
| 819 | 797 | |
| 820 | - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() | |
| 821 | - : udpSipProvider.getNewCallId(); | |
| 822 | - | |
| 823 | - Request request = headerProvider.createMessageRequest(device, broadcastXml.toString(), "z9hG4bK-ViaBcst-" + tm, "FromBcst" + tm, null, callIdHeader); | |
| 824 | - transmitRequest(device, request, errorEvent); | |
| 825 | - } catch (SipException | ParseException | InvalidArgumentException e) { | |
| 826 | - e.printStackTrace(); | |
| 827 | - } | |
| 828 | - } | |
| 829 | - | |
| 830 | - | |
| 831 | 798 | /** |
| 832 | 799 | * 音视频录像控制 |
| 833 | 800 | * | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
| ... | ... | @@ -94,6 +94,9 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In |
| 94 | 94 | param.put("dst_port", sendRtpItem.getPort()); |
| 95 | 95 | param.put("is_udp", is_Udp); |
| 96 | 96 | param.put("src_port", sendRtpItem.getLocalPort()); |
| 97 | + param.put("pt", 8); | |
| 98 | + param.put("use_ps", 0); | |
| 99 | + param.put("only_audio", 1); | |
| 97 | 100 | zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); |
| 98 | 101 | |
| 99 | 102 | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
| ... | ... | @@ -2,21 +2,27 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; |
| 2 | 2 | |
| 3 | 3 | import com.alibaba.fastjson.JSONObject; |
| 4 | 4 | import com.genersoft.iot.vmp.conf.DynamicTask; |
| 5 | +import com.genersoft.iot.vmp.conf.SipConfig; | |
| 5 | 6 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 6 | 7 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 7 | 8 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| 9 | +import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; | |
| 8 | 10 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 9 | 11 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
| 12 | +import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; | |
| 13 | +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | |
| 10 | 14 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; |
| 11 | 15 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; |
| 12 | 16 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; |
| 13 | 17 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; |
| 14 | 18 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
| 15 | 19 | import com.genersoft.iot.vmp.gb28181.utils.SipUtils; |
| 20 | +import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; | |
| 16 | 21 | import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; |
| 17 | 22 | import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager; |
| 18 | 23 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
| 19 | 24 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 25 | +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItemLite; | |
| 20 | 26 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| 21 | 27 | import com.genersoft.iot.vmp.service.IPlayService; |
| 22 | 28 | import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; |
| ... | ... | @@ -24,8 +30,12 @@ import com.genersoft.iot.vmp.service.bean.SSRCInfo; |
| 24 | 30 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 25 | 31 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 26 | 32 | import com.genersoft.iot.vmp.utils.SerializeUtils; |
| 33 | +import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; | |
| 34 | +import com.genersoft.iot.vmp.vmanager.bean.WVPResult; | |
| 27 | 35 | import gov.nist.javax.sdp.TimeDescriptionImpl; |
| 28 | 36 | import gov.nist.javax.sdp.fields.TimeField; |
| 37 | +import gov.nist.javax.sip.message.SIPRequest; | |
| 38 | +import gov.nist.javax.sip.stack.SIPDialog; | |
| 29 | 39 | import org.slf4j.Logger; |
| 30 | 40 | import org.slf4j.LoggerFactory; |
| 31 | 41 | import org.springframework.beans.factory.InitializingBean; |
| ... | ... | @@ -41,6 +51,7 @@ import javax.sip.message.Response; |
| 41 | 51 | import java.text.ParseException; |
| 42 | 52 | import java.text.SimpleDateFormat; |
| 43 | 53 | import java.util.Date; |
| 54 | +import java.util.List; | |
| 44 | 55 | import java.util.Vector; |
| 45 | 56 | |
| 46 | 57 | /** |
| ... | ... | @@ -73,7 +84,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 73 | 84 | private IPlayService playService; |
| 74 | 85 | |
| 75 | 86 | @Autowired |
| 76 | - private ISIPCommander commander; | |
| 87 | + private AudioBroadcastManager audioBroadcastManager; | |
| 77 | 88 | |
| 78 | 89 | @Autowired |
| 79 | 90 | private ZLMRTPServerFactory zlmrtpServerFactory; |
| ... | ... | @@ -93,6 +104,15 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 93 | 104 | @Autowired |
| 94 | 105 | private ZLMMediaListManager mediaListManager; |
| 95 | 106 | |
| 107 | + @Autowired | |
| 108 | + private DeferredResultHolder resultHolder; | |
| 109 | + | |
| 110 | + @Autowired | |
| 111 | + private ZLMHttpHookSubscribe subscribe; | |
| 112 | + | |
| 113 | + @Autowired | |
| 114 | + private SipConfig config; | |
| 115 | + | |
| 96 | 116 | |
| 97 | 117 | @Override |
| 98 | 118 | public void afterPropertiesSet() throws Exception { |
| ... | ... | @@ -126,7 +146,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 126 | 146 | // 查询请求是否来自上级平台\设备 |
| 127 | 147 | ParentPlatform platform = storager.queryParentPlatByServerGBId(requesterId); |
| 128 | 148 | if (platform == null) { |
| 129 | - inviteFromDeviceHandle(evt, requesterId); | |
| 149 | + inviteFromDeviceHandle(evt, requesterId, channelId); | |
| 130 | 150 | }else { |
| 131 | 151 | // 查询平台下是否有该通道 |
| 132 | 152 | DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId); |
| ... | ... | @@ -542,10 +562,25 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 542 | 562 | } |
| 543 | 563 | } |
| 544 | 564 | |
| 545 | - public void inviteFromDeviceHandle(RequestEvent evt, String requesterId) throws InvalidArgumentException, ParseException, SipException, SdpException { | |
| 546 | - | |
| 565 | + public void inviteFromDeviceHandle(RequestEvent evt, String requesterId, String channelId) throws InvalidArgumentException, ParseException, SipException, SdpException { | |
| 566 | + | |
| 567 | + // 兼容奇葩的海康这里使用的不是通道编号而是本平台编号 | |
| 568 | +// if (channelId.equals(config.getId())) { | |
| 569 | +// List<AudioBroadcastCatch> all = audioBroadcastManager.getAll(); | |
| 570 | +// for (AudioBroadcastCatch audioBroadcastCatch : all) { | |
| 571 | +// if (audioBroadcastCatch.getDeviceId().equals(requesterId)) { | |
| 572 | +// channelId = audioBroadcastCatch.getChannelId(); | |
| 573 | +// } | |
| 574 | +// } | |
| 575 | +// } | |
| 576 | +// // 兼容失败 | |
| 577 | +// if (channelId.equals(config.getId())) { | |
| 578 | +// responseAck(evt, Response.BAD_REQUEST); | |
| 579 | +// return; | |
| 580 | +// } | |
| 547 | 581 | // 非上级平台请求,查询是否设备请求(通常为接收语音广播的设备) |
| 548 | 582 | Device device = redisCatchStorage.getDevice(requesterId); |
| 583 | + | |
| 549 | 584 | Request request = evt.getRequest(); |
| 550 | 585 | if (device != null) { |
| 551 | 586 | logger.info("收到设备" + requesterId + "的语音广播Invite请求"); |
| ... | ... | @@ -558,7 +593,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 558 | 593 | int ssrcIndex = contentString.indexOf("y="); |
| 559 | 594 | if (ssrcIndex > 0) { |
| 560 | 595 | substring = contentString.substring(0, ssrcIndex); |
| 561 | - ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); | |
| 596 | + ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12).trim(); | |
| 562 | 597 | } |
| 563 | 598 | ssrcIndex = substring.indexOf("f="); |
| 564 | 599 | if (ssrcIndex > 0) { |
| ... | ... | @@ -568,6 +603,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 568 | 603 | |
| 569 | 604 | // 获取支持的格式 |
| 570 | 605 | Vector mediaDescriptions = sdp.getMediaDescriptions(true); |
| 606 | + | |
| 571 | 607 | // 查看是否支持PS 负载96 |
| 572 | 608 | int port = -1; |
| 573 | 609 | //boolean recvonly = false; |
| ... | ... | @@ -602,10 +638,150 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 602 | 638 | responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415 |
| 603 | 639 | return; |
| 604 | 640 | } |
| 605 | - String username = sdp.getOrigin().getUsername(); | |
| 641 | + String sessionName = sdp.getSessionName().getValue(); | |
| 606 | 642 | String addressStr = sdp.getOrigin().getAddress(); |
| 607 | - logger.info("设备{}请求语音流,地址:{}:{},ssrc:{}", username, addressStr, port, ssrc); | |
| 643 | + logger.info("设备{}请求语音流,地址:{}:{},ssrc:{}", requesterId, addressStr, port, ssrc); | |
| 644 | + | |
| 645 | + MediaServerItem mediaServerItem = playService.getNewMediaServerItem(device); | |
| 646 | + if (mediaServerItem == null) { | |
| 647 | + logger.warn("未找到可用的zlm"); | |
| 648 | + responseAck(evt, Response.BUSY_HERE); | |
| 649 | + return; | |
| 650 | + } | |
| 651 | + SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, | |
| 652 | + device.getDeviceId(), channelId, | |
| 653 | + mediaTransmissionTCP); | |
| 654 | + sendRtpItem.setTcp(mediaTransmissionTCP); | |
| 655 | + if (tcpActive != null) { | |
| 656 | + sendRtpItem.setTcpActive(tcpActive); | |
| 657 | + } | |
| 658 | + if (sendRtpItem == null) { | |
| 659 | + logger.warn("服务器端口资源不足"); | |
| 660 | + responseAck(evt, Response.BUSY_HERE); | |
| 661 | + return; | |
| 662 | + } | |
| 663 | + | |
| 664 | + String app = "broadcast"; | |
| 665 | + String stream = device.getDeviceId() + "_" + channelId; | |
| 666 | + | |
| 667 | + CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME); | |
| 668 | + sendRtpItem.setPlayType(InviteStreamType.PLAY); | |
| 669 | + sendRtpItem.setCallId(callIdHeader.getCallId()); | |
| 670 | + sendRtpItem.setPlatformId(requesterId); | |
| 671 | + sendRtpItem.setStatus(1); | |
| 672 | + sendRtpItem.setApp(app); | |
| 673 | + sendRtpItem.setStreamId(stream); | |
| 674 | + redisCatchStorage.updateSendRTPSever(sendRtpItem); | |
| 675 | + | |
| 676 | + // hook监听等待设备推流上来 | |
| 677 | + // 添加订阅 | |
| 678 | + JSONObject subscribeKey = new JSONObject(); | |
| 679 | + subscribeKey.put("app", app); | |
| 680 | + subscribeKey.put("stream", stream); | |
| 681 | + subscribeKey.put("regist", true); | |
| 682 | + subscribeKey.put("schema", "rtmp"); | |
| 683 | + subscribeKey.put("mediaServerId", mediaServerItem.getId()); | |
| 684 | + String finalSsrc = ssrc; | |
| 685 | + String waiteStreamTimeoutTaskKey = "waite-stream-" + device.getDeviceId() + channelId; | |
| 686 | + if (zlmrtpServerFactory.isStreamReady(mediaServerItem, app, stream)) { | |
| 687 | + logger.info("发现已经在推流"); | |
| 688 | + dynamicTask.stop(waiteStreamTimeoutTaskKey); | |
| 689 | + sendRtpItem.setStatus(2); | |
| 690 | + redisCatchStorage.updateSendRTPSever(sendRtpItem); | |
| 691 | + StringBuffer content = new StringBuffer(200); | |
| 692 | + content.append("v=0\r\n"); | |
| 693 | + content.append("o="+ config.getId() +" "+ sdp.getOrigin().getSessionId() +" " + sdp.getOrigin().getSessionVersion() + " IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); | |
| 694 | + content.append("s=Play\r\n"); | |
| 695 | + content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); | |
| 696 | + content.append("t=0 0\r\n"); | |
| 697 | + content.append("m=audio "+ sendRtpItem.getLocalPort()+" RTP/AVP 8\r\n"); | |
| 698 | + content.append("a=sendonly\r\n"); | |
| 699 | + content.append("a=rtpmap:8 PCMA/8000\r\n"); | |
| 700 | + content.append("y="+ finalSsrc + "\r\n"); | |
| 701 | + content.append("f=v/////a/1/8/1\r\n"); | |
| 702 | + | |
| 703 | + ParentPlatform parentPlatform = new ParentPlatform(); | |
| 704 | + parentPlatform.setServerIP(device.getIp()); | |
| 705 | + parentPlatform.setServerPort(device.getPort()); | |
| 706 | + parentPlatform.setServerGBId(device.getDeviceId()); | |
| 707 | + try { | |
| 708 | + responseSdpAck(evt, content.toString(), parentPlatform); | |
| 709 | + } catch (SipException e) { | |
| 710 | + throw new RuntimeException(e); | |
| 711 | + } catch (InvalidArgumentException e) { | |
| 712 | + throw new RuntimeException(e); | |
| 713 | + } catch (ParseException e) { | |
| 714 | + throw new RuntimeException(e); | |
| 715 | + } | |
| 716 | + }else { | |
| 717 | + // 设置等待推流的超时; 默认20s | |
| 718 | + String finalChannelId = channelId; | |
| 719 | + dynamicTask.startDelay(waiteStreamTimeoutTaskKey, ()->{ | |
| 720 | + logger.info("等待推流超时: {}/{}", app, stream); | |
| 721 | + if (audioBroadcastManager.exit(device.getDeviceId(), finalChannelId)) { | |
| 722 | + audioBroadcastManager.del(device.getDeviceId(), finalChannelId); | |
| 723 | + }else { | |
| 724 | + // 兼容海康使用了错误的通道ID的情况 | |
| 725 | + audioBroadcastManager.delByDeviceId(device.getDeviceId()); | |
| 726 | + } | |
| 608 | 727 | |
| 728 | + // 发送bye | |
| 729 | + try { | |
| 730 | + cmder.streamByeCmd((SIPDialog)evt.getServerTransaction().getDialog(), (SIPRequest) evt.getRequest(), null); | |
| 731 | + } catch (SipException e) { | |
| 732 | + throw new RuntimeException(e); | |
| 733 | + } catch (ParseException e) { | |
| 734 | + throw new RuntimeException(e); | |
| 735 | + } | |
| 736 | + }, 20*1000); | |
| 737 | + | |
| 738 | + subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, | |
| 739 | + (MediaServerItem mediaServerItemInUse, JSONObject json)->{ | |
| 740 | + sendRtpItem.setStatus(2); | |
| 741 | + redisCatchStorage.updateSendRTPSever(sendRtpItem); | |
| 742 | + StringBuffer content = new StringBuffer(200); | |
| 743 | + content.append("v=0\r\n"); | |
| 744 | + content.append("o="+ finalChannelId +" 0 0 IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); | |
| 745 | + content.append("s=Play\r\n"); | |
| 746 | + content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); | |
| 747 | + content.append("t=0 0\r\n"); | |
| 748 | + content.append("m=video "+ sendRtpItem.getLocalPort()+" RTP/AVP 8\r\n"); | |
| 749 | + content.append("a=sendonly\r\n"); | |
| 750 | + content.append("a=rtpmap:8 PCMA/8000\r\n"); | |
| 751 | + content.append("y="+ finalSsrc + "\r\n"); | |
| 752 | + content.append("f=v/////a/1/8/1\r\n"); | |
| 753 | + | |
| 754 | + ParentPlatform parentPlatform = new ParentPlatform(); | |
| 755 | + parentPlatform.setServerIP(device.getIp()); | |
| 756 | + parentPlatform.setServerPort(device.getPort()); | |
| 757 | + parentPlatform.setServerGBId(device.getDeviceId()); | |
| 758 | + try { | |
| 759 | + responseSdpAck(evt, content.toString(), parentPlatform); | |
| 760 | + } catch (SipException e) { | |
| 761 | + throw new RuntimeException(e); | |
| 762 | + } catch (InvalidArgumentException e) { | |
| 763 | + throw new RuntimeException(e); | |
| 764 | + } catch (ParseException e) { | |
| 765 | + throw new RuntimeException(e); | |
| 766 | + } | |
| 767 | + }); | |
| 768 | + } | |
| 769 | + String timeOutTaskKey = "audio-broadcast-" + device.getDeviceId() + channelId; | |
| 770 | + dynamicTask.stop(timeOutTaskKey); | |
| 771 | + String key = DeferredResultHolder.CALLBACK_CMD_BROADCAST + device.getDeviceId(); | |
| 772 | + WVPResult<AudioBroadcastResult> wvpResult = new WVPResult<>(); | |
| 773 | + wvpResult.setCode(0); | |
| 774 | + wvpResult.setMsg("success"); | |
| 775 | + AudioBroadcastResult audioBroadcastResult = new AudioBroadcastResult(); | |
| 776 | + audioBroadcastResult.setApp(app); | |
| 777 | + audioBroadcastResult.setStream(stream); | |
| 778 | + audioBroadcastResult.setMediaServerItem(new MediaServerItemLite(mediaServerItem)); | |
| 779 | + audioBroadcastResult.setCodec("G.711"); | |
| 780 | + wvpResult.setData(audioBroadcastResult); | |
| 781 | + RequestMessage requestMessage = new RequestMessage(); | |
| 782 | + requestMessage.setKey(key); | |
| 783 | + requestMessage.setData(wvpResult); | |
| 784 | + resultHolder.invokeAllResult(requestMessage); | |
| 609 | 785 | } else { |
| 610 | 786 | logger.warn("来自无效设备/平台的请求"); |
| 611 | 787 | responseAck(evt, Response.BAD_REQUEST); | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageHandlerAbstract.java
| ... | ... | @@ -6,7 +6,11 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorP |
| 6 | 6 | import org.dom4j.Element; |
| 7 | 7 | import org.springframework.beans.factory.annotation.Autowired; |
| 8 | 8 | |
| 9 | +import javax.sip.InvalidArgumentException; | |
| 9 | 10 | import javax.sip.RequestEvent; |
| 11 | +import javax.sip.SipException; | |
| 12 | +import javax.sip.message.Response; | |
| 13 | +import java.text.ParseException; | |
| 10 | 14 | import java.util.Map; |
| 11 | 15 | import java.util.concurrent.ConcurrentHashMap; |
| 12 | 16 | |
| ... | ... | @@ -23,6 +27,10 @@ public abstract class MessageHandlerAbstract extends SIPRequestProcessorParent i |
| 23 | 27 | @Override |
| 24 | 28 | public void handForDevice(RequestEvent evt, Device device, Element element) { |
| 25 | 29 | String cmd = getText(element, "CmdType"); |
| 30 | + if (cmd == null) { | |
| 31 | + handNullCmd(evt); | |
| 32 | + return; | |
| 33 | + } | |
| 26 | 34 | IMessageHandler messageHandler = messageHandlerMap.get(cmd); |
| 27 | 35 | if (messageHandler != null) { |
| 28 | 36 | messageHandler.handForDevice(evt, device, element); |
| ... | ... | @@ -37,4 +45,17 @@ public abstract class MessageHandlerAbstract extends SIPRequestProcessorParent i |
| 37 | 45 | messageHandler.handForPlatform(evt, parentPlatform, element); |
| 38 | 46 | } |
| 39 | 47 | } |
| 48 | + | |
| 49 | + public void handNullCmd(RequestEvent evt){ | |
| 50 | + try { | |
| 51 | + responseAck(evt, Response.OK); | |
| 52 | + } catch (SipException e) { | |
| 53 | + throw new RuntimeException(e); | |
| 54 | + } catch (InvalidArgumentException e) { | |
| 55 | + throw new RuntimeException(e); | |
| 56 | + } catch (ParseException e) { | |
| 57 | + throw new RuntimeException(e); | |
| 58 | + } | |
| 59 | + return; | |
| 60 | + } | |
| 40 | 61 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/BroadcastResponseMessageHandler.java
| 1 | 1 | package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd; |
| 2 | 2 | |
| 3 | 3 | import com.alibaba.fastjson.JSONObject; |
| 4 | +import com.genersoft.iot.vmp.gb28181.bean.AudioBroadcastCatch; | |
| 5 | +import com.genersoft.iot.vmp.gb28181.bean.AudioBroadcastCatchStatus; | |
| 4 | 6 | import com.genersoft.iot.vmp.gb28181.bean.Device; |
| 5 | 7 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| 8 | +import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; | |
| 6 | 9 | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
| 7 | 10 | import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; |
| 8 | 11 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
| ... | ... | @@ -36,6 +39,9 @@ public class BroadcastResponseMessageHandler extends SIPRequestProcessorParent i |
| 36 | 39 | @Autowired |
| 37 | 40 | private DeferredResultHolder deferredResultHolder; |
| 38 | 41 | |
| 42 | + @Autowired | |
| 43 | + private AudioBroadcastManager audioBroadcastManager; | |
| 44 | + | |
| 39 | 45 | @Override |
| 40 | 46 | public void afterPropertiesSet() throws Exception { |
| 41 | 47 | responseMessageHandler.addHandler(cmdType, this); |
| ... | ... | @@ -45,21 +51,16 @@ public class BroadcastResponseMessageHandler extends SIPRequestProcessorParent i |
| 45 | 51 | public void handForDevice(RequestEvent evt, Device device, Element rootElement) { |
| 46 | 52 | try { |
| 47 | 53 | String channelId = getText(rootElement, "DeviceID"); |
| 48 | - String key = DeferredResultHolder.CALLBACK_CMD_BROADCAST + device.getDeviceId() + channelId; | |
| 49 | - // 回复200 OK | |
| 50 | - responseAck(evt, Response.OK); | |
| 51 | - // 此处是对本平台发出Broadcast指令的应答 | |
| 52 | - JSONObject json = new JSONObject(); | |
| 53 | - XmlUtil.node2Json(rootElement, json); | |
| 54 | - if (logger.isDebugEnabled()) { | |
| 55 | - logger.debug(json.toJSONString()); | |
| 54 | + if (!audioBroadcastManager.exit(device.getDeviceId(), channelId)) { | |
| 55 | + // 回复410 | |
| 56 | + responseAck(evt, Response.GONE); | |
| 57 | + return; | |
| 56 | 58 | } |
| 57 | - RequestMessage msg = new RequestMessage(); | |
| 58 | - msg.setKey(key); | |
| 59 | - msg.setData(json); | |
| 60 | - deferredResultHolder.invokeAllResult(msg); | |
| 61 | - | |
| 62 | - | |
| 59 | + logger.info("收到语音广播的回复:{}/{}", device.getDeviceId(), channelId ); | |
| 60 | + AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(device.getDeviceId(), channelId); | |
| 61 | + audioBroadcastCatch.setStatus(AudioBroadcastCatchStatus.WaiteInvite); | |
| 62 | + audioBroadcastManager.update(audioBroadcastCatch); | |
| 63 | + responseAck(evt, Response.OK); | |
| 63 | 64 | } catch (ParseException | SipException | InvalidArgumentException e) { |
| 64 | 65 | e.printStackTrace(); |
| 65 | 66 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
| ... | ... | @@ -271,7 +271,7 @@ public class ZLMRTPServerFactory { |
| 271 | 271 | * 查询待转推的流是否就绪 |
| 272 | 272 | */ |
| 273 | 273 | public Boolean isStreamReady(MediaServerItem mediaServerItem, String app, String streamId) { |
| 274 | - JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtmp", streamId); | |
| 274 | + JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtsp", streamId); | |
| 275 | 275 | return (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online")); |
| 276 | 276 | } |
| 277 | 277 | ... | ... |
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItemLite.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.media.zlm.dto; | |
| 2 | + | |
| 3 | + | |
| 4 | +import com.genersoft.iot.vmp.gb28181.session.SsrcConfig; | |
| 5 | +import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; | |
| 6 | +import org.springframework.util.StringUtils; | |
| 7 | + | |
| 8 | +import java.util.HashMap; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * 精简的MediaServerItem信息,方便给前端返回数据 | |
| 12 | + */ | |
| 13 | +public class MediaServerItemLite { | |
| 14 | + | |
| 15 | + private String id; | |
| 16 | + | |
| 17 | + private String ip; | |
| 18 | + | |
| 19 | + private String hookIp; | |
| 20 | + | |
| 21 | + private String sdpIp; | |
| 22 | + | |
| 23 | + private String streamIp; | |
| 24 | + | |
| 25 | + private int httpPort; | |
| 26 | + | |
| 27 | + private int httpSSlPort; | |
| 28 | + | |
| 29 | + private int rtmpPort; | |
| 30 | + | |
| 31 | + private int rtmpSSlPort; | |
| 32 | + | |
| 33 | + private int rtpProxyPort; | |
| 34 | + | |
| 35 | + private int rtspPort; | |
| 36 | + | |
| 37 | + private int rtspSSLPort; | |
| 38 | + | |
| 39 | + private String secret; | |
| 40 | + | |
| 41 | + private int streamNoneReaderDelayMS; | |
| 42 | + | |
| 43 | + private int hookAliveInterval; | |
| 44 | + | |
| 45 | + private int recordAssistPort; | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + public MediaServerItemLite(MediaServerItem mediaServerItem) { | |
| 50 | + this.id = mediaServerItem.getId(); | |
| 51 | + this.ip = mediaServerItem.getIp(); | |
| 52 | + this.hookIp = mediaServerItem.getHookIp(); | |
| 53 | + this.sdpIp = mediaServerItem.getSdpIp(); | |
| 54 | + this.streamIp = mediaServerItem.getStreamIp(); | |
| 55 | + this.httpPort = mediaServerItem.getHttpPort(); | |
| 56 | + this.httpSSlPort = mediaServerItem.getHttpSSlPort(); | |
| 57 | + this.rtmpPort = mediaServerItem.getRtmpPort(); | |
| 58 | + this.rtmpSSlPort = mediaServerItem.getRtmpSSlPort(); | |
| 59 | + this.rtpProxyPort = mediaServerItem.getRtpProxyPort(); | |
| 60 | + this.rtspPort = mediaServerItem.getRtspPort(); | |
| 61 | + this.rtspSSLPort = mediaServerItem.getRtspSSLPort(); | |
| 62 | + this.secret = mediaServerItem.getSecret(); | |
| 63 | + this.streamNoneReaderDelayMS = mediaServerItem.getStreamNoneReaderDelayMS(); | |
| 64 | + this.hookAliveInterval = mediaServerItem.getHookAliveInterval(); | |
| 65 | + this.streamNoneReaderDelayMS = mediaServerItem.getStreamNoneReaderDelayMS(); | |
| 66 | + this.recordAssistPort = mediaServerItem.getRecordAssistPort(); | |
| 67 | + } | |
| 68 | + | |
| 69 | + public String getId() { | |
| 70 | + return id; | |
| 71 | + } | |
| 72 | + | |
| 73 | + public void setId(String id) { | |
| 74 | + this.id = id; | |
| 75 | + } | |
| 76 | + | |
| 77 | + public String getIp() { | |
| 78 | + return ip; | |
| 79 | + } | |
| 80 | + | |
| 81 | + public void setIp(String ip) { | |
| 82 | + this.ip = ip; | |
| 83 | + } | |
| 84 | + | |
| 85 | + public String getHookIp() { | |
| 86 | + return hookIp; | |
| 87 | + } | |
| 88 | + | |
| 89 | + public void setHookIp(String hookIp) { | |
| 90 | + this.hookIp = hookIp; | |
| 91 | + } | |
| 92 | + | |
| 93 | + public String getSdpIp() { | |
| 94 | + return sdpIp; | |
| 95 | + } | |
| 96 | + | |
| 97 | + public void setSdpIp(String sdpIp) { | |
| 98 | + this.sdpIp = sdpIp; | |
| 99 | + } | |
| 100 | + | |
| 101 | + public String getStreamIp() { | |
| 102 | + return streamIp; | |
| 103 | + } | |
| 104 | + | |
| 105 | + public void setStreamIp(String streamIp) { | |
| 106 | + this.streamIp = streamIp; | |
| 107 | + } | |
| 108 | + | |
| 109 | + public int getHttpPort() { | |
| 110 | + return httpPort; | |
| 111 | + } | |
| 112 | + | |
| 113 | + public void setHttpPort(int httpPort) { | |
| 114 | + this.httpPort = httpPort; | |
| 115 | + } | |
| 116 | + | |
| 117 | + public int getHttpSSlPort() { | |
| 118 | + return httpSSlPort; | |
| 119 | + } | |
| 120 | + | |
| 121 | + public void setHttpSSlPort(int httpSSlPort) { | |
| 122 | + this.httpSSlPort = httpSSlPort; | |
| 123 | + } | |
| 124 | + | |
| 125 | + public int getRtmpPort() { | |
| 126 | + return rtmpPort; | |
| 127 | + } | |
| 128 | + | |
| 129 | + public void setRtmpPort(int rtmpPort) { | |
| 130 | + this.rtmpPort = rtmpPort; | |
| 131 | + } | |
| 132 | + | |
| 133 | + public int getRtmpSSlPort() { | |
| 134 | + return rtmpSSlPort; | |
| 135 | + } | |
| 136 | + | |
| 137 | + public void setRtmpSSlPort(int rtmpSSlPort) { | |
| 138 | + this.rtmpSSlPort = rtmpSSlPort; | |
| 139 | + } | |
| 140 | + | |
| 141 | + public int getRtpProxyPort() { | |
| 142 | + return rtpProxyPort; | |
| 143 | + } | |
| 144 | + | |
| 145 | + public void setRtpProxyPort(int rtpProxyPort) { | |
| 146 | + this.rtpProxyPort = rtpProxyPort; | |
| 147 | + } | |
| 148 | + | |
| 149 | + public int getRtspPort() { | |
| 150 | + return rtspPort; | |
| 151 | + } | |
| 152 | + | |
| 153 | + public void setRtspPort(int rtspPort) { | |
| 154 | + this.rtspPort = rtspPort; | |
| 155 | + } | |
| 156 | + | |
| 157 | + public int getRtspSSLPort() { | |
| 158 | + return rtspSSLPort; | |
| 159 | + } | |
| 160 | + | |
| 161 | + public void setRtspSSLPort(int rtspSSLPort) { | |
| 162 | + this.rtspSSLPort = rtspSSLPort; | |
| 163 | + } | |
| 164 | + | |
| 165 | + | |
| 166 | + public String getSecret() { | |
| 167 | + return secret; | |
| 168 | + } | |
| 169 | + | |
| 170 | + public void setSecret(String secret) { | |
| 171 | + this.secret = secret; | |
| 172 | + } | |
| 173 | + | |
| 174 | + public int getStreamNoneReaderDelayMS() { | |
| 175 | + return streamNoneReaderDelayMS; | |
| 176 | + } | |
| 177 | + | |
| 178 | + public void setStreamNoneReaderDelayMS(int streamNoneReaderDelayMS) { | |
| 179 | + this.streamNoneReaderDelayMS = streamNoneReaderDelayMS; | |
| 180 | + } | |
| 181 | + | |
| 182 | + public int getHookAliveInterval() { | |
| 183 | + return hookAliveInterval; | |
| 184 | + } | |
| 185 | + | |
| 186 | + public void setHookAliveInterval(int hookAliveInterval) { | |
| 187 | + this.hookAliveInterval = hookAliveInterval; | |
| 188 | + } | |
| 189 | + | |
| 190 | + public int getRecordAssistPort() { | |
| 191 | + return recordAssistPort; | |
| 192 | + } | |
| 193 | + | |
| 194 | + public void setRecordAssistPort(int recordAssistPort) { | |
| 195 | + this.recordAssistPort = recordAssistPort; | |
| 196 | + } | |
| 197 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
| ... | ... | @@ -11,6 +11,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 11 | 11 | import com.genersoft.iot.vmp.service.bean.InviteTimeOutCallback; |
| 12 | 12 | import com.genersoft.iot.vmp.service.bean.PlayBackCallback; |
| 13 | 13 | import com.genersoft.iot.vmp.service.bean.SSRCInfo; |
| 14 | +import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent; | |
| 14 | 15 | import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; |
| 15 | 16 | import org.springframework.http.ResponseEntity; |
| 16 | 17 | import org.springframework.web.context.request.async.DeferredResult; |
| ... | ... | @@ -40,4 +41,6 @@ public interface IPlayService { |
| 40 | 41 | DeferredResult<ResponseEntity<String>> download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack); |
| 41 | 42 | |
| 42 | 43 | StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream); |
| 44 | + | |
| 45 | + void audioBroadcast(Device device, String channelId, int timeout, AudioBroadcastEvent event); | |
| 43 | 46 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
| ... | ... | @@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.conf.DynamicTask; |
| 8 | 8 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 9 | 9 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 10 | 10 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| 11 | +import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; | |
| 11 | 12 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 12 | 13 | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
| 13 | 14 | import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; |
| ... | ... | @@ -26,7 +27,9 @@ import com.genersoft.iot.vmp.service.bean.SSRCInfo; |
| 26 | 27 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 27 | 28 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 28 | 29 | import com.genersoft.iot.vmp.utils.redis.RedisUtil; |
| 30 | +import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; | |
| 29 | 31 | import com.genersoft.iot.vmp.vmanager.bean.WVPResult; |
| 32 | +import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent; | |
| 30 | 33 | import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; |
| 31 | 34 | import com.genersoft.iot.vmp.service.IMediaService; |
| 32 | 35 | import com.genersoft.iot.vmp.service.IPlayService; |
| ... | ... | @@ -58,6 +61,9 @@ public class PlayServiceImpl implements IPlayService { |
| 58 | 61 | private SIPCommander cmder; |
| 59 | 62 | |
| 60 | 63 | @Autowired |
| 64 | + private AudioBroadcastManager audioBroadcastManager; | |
| 65 | + | |
| 66 | + @Autowired | |
| 61 | 67 | private SIPCommanderFroPlatform sipCommanderFroPlatform; |
| 62 | 68 | |
| 63 | 69 | @Autowired |
| ... | ... | @@ -621,4 +627,42 @@ public class PlayServiceImpl implements IPlayService { |
| 621 | 627 | } |
| 622 | 628 | } |
| 623 | 629 | } |
| 630 | + | |
| 631 | + @Override | |
| 632 | + public void audioBroadcast(Device device, String channelId, int timeout, AudioBroadcastEvent event) { | |
| 633 | + if (device == null || channelId == null) { | |
| 634 | + return; | |
| 635 | + } | |
| 636 | + DeviceChannel deviceChannel = storager.queryChannel(device.getDeviceId(), channelId); | |
| 637 | + if (deviceChannel == null) { | |
| 638 | + logger.warn("开启语音广播的时候未找到通道: {}", channelId); | |
| 639 | + event.call("开启语音广播的时候未找到通道"); | |
| 640 | + return; | |
| 641 | + } | |
| 642 | + // 查询通道使用状态 | |
| 643 | + if (audioBroadcastManager.exit(device.getDeviceId(), channelId)) { | |
| 644 | + logger.warn("语音广播已经开启: {}", channelId); | |
| 645 | + event.call("语音广播已经开启"); | |
| 646 | + return; | |
| 647 | + } | |
| 648 | + String timeOutTaskKey = "audio-broadcast-" + device.getDeviceId() + channelId; | |
| 649 | + dynamicTask.startDelay(timeOutTaskKey, ()->{ | |
| 650 | + logger.error("语音广播发送超时: {}:{}", device.getDeviceId(), channelId); | |
| 651 | + event.call("语音广播发送超时"); | |
| 652 | + audioBroadcastManager.del(device.getDeviceId(), channelId); | |
| 653 | + }, timeout * 1000); | |
| 654 | + | |
| 655 | + // 发送通知 | |
| 656 | + cmder.audioBroadcastCmd(device, channelId, eventResultForOk -> { | |
| 657 | + // 发送成功 | |
| 658 | + AudioBroadcastCatch audioBroadcastCatch = new AudioBroadcastCatch(device.getDeviceId(), channelId, AudioBroadcastCatchStatus.Ready); | |
| 659 | + audioBroadcastManager.add(audioBroadcastCatch); | |
| 660 | + }, eventResultForError -> { | |
| 661 | + dynamicTask.stop(timeOutTaskKey); | |
| 662 | + // 发送失败 | |
| 663 | + logger.error("语音广播发送失败: {}:{}", channelId, eventResultForError.msg); | |
| 664 | + event.call("语音广播发送失败"); | |
| 665 | + audioBroadcastManager.del(device.getDeviceId(), channelId); | |
| 666 | + }); | |
| 667 | + } | |
| 624 | 668 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java
| ... | ... | @@ -37,8 +37,6 @@ public interface DeviceMapper { |
| 37 | 37 | "subscribeCycleForMobilePosition," + |
| 38 | 38 | "mobilePositionSubmissionInterval," + |
| 39 | 39 | "subscribeCycleForAlarm," + |
| 40 | - "audioChannelForReceive," + | |
| 41 | - "audioChannelForSend," + | |
| 42 | 40 | "ssrcCheck," + |
| 43 | 41 | "online" + |
| 44 | 42 | ") VALUES (" + |
| ... | ... | @@ -62,8 +60,6 @@ public interface DeviceMapper { |
| 62 | 60 | "#{subscribeCycleForMobilePosition}," + |
| 63 | 61 | "#{mobilePositionSubmissionInterval}," + |
| 64 | 62 | "#{subscribeCycleForAlarm}," + |
| 65 | - "#{audioChannelForReceive}," + | |
| 66 | - "#{audioChannelForSend}," + | |
| 67 | 63 | "#{ssrcCheck}," + |
| 68 | 64 | "#{online}" + |
| 69 | 65 | ")") |
| ... | ... | @@ -90,8 +86,6 @@ public interface DeviceMapper { |
| 90 | 86 | "<if test=\"subscribeCycleForMobilePosition != null\">, subscribeCycleForMobilePosition=${subscribeCycleForMobilePosition}</if>" + |
| 91 | 87 | "<if test=\"mobilePositionSubmissionInterval != null\">, mobilePositionSubmissionInterval=${mobilePositionSubmissionInterval}</if>" + |
| 92 | 88 | "<if test=\"subscribeCycleForAlarm != null\">, subscribeCycleForAlarm=${subscribeCycleForAlarm}</if>" + |
| 93 | - "<if test=\"audioChannelForReceive != null\">, audioChannelForReceive=#{audioChannelForReceive}</if>" + | |
| 94 | - "<if test=\"audioChannelForSend != null\">, audioChannelForSend=#{audioChannelForSend}</if>" + | |
| 95 | 89 | "<if test=\"ssrcCheck != null\">, ssrcCheck=${ssrcCheck}</if>" + |
| 96 | 90 | "WHERE deviceId='${deviceId}'"+ |
| 97 | 91 | " </script>"}) | ... | ... |
src/main/java/com/genersoft/iot/vmp/vmanager/bean/AudioBroadcastResult.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.vmanager.bean; | |
| 2 | + | |
| 3 | +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | |
| 4 | +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItemLite; | |
| 5 | + | |
| 6 | +/** | |
| 7 | + * @author lin | |
| 8 | + */ | |
| 9 | +public class AudioBroadcastResult { | |
| 10 | + /** | |
| 11 | + * 推流的媒体节点信息 | |
| 12 | + */ | |
| 13 | + private MediaServerItemLite mediaServerItem; | |
| 14 | + | |
| 15 | + /** | |
| 16 | + * 编码格式 | |
| 17 | + */ | |
| 18 | + private String codec; | |
| 19 | + | |
| 20 | + /** | |
| 21 | + * 向zlm推流的应用名 | |
| 22 | + */ | |
| 23 | + private String app; | |
| 24 | + | |
| 25 | + /** | |
| 26 | + * 向zlm推流的流ID | |
| 27 | + */ | |
| 28 | + private String stream; | |
| 29 | + | |
| 30 | + | |
| 31 | + public MediaServerItemLite getMediaServerItem() { | |
| 32 | + return mediaServerItem; | |
| 33 | + } | |
| 34 | + | |
| 35 | + public void setMediaServerItem(MediaServerItemLite mediaServerItem) { | |
| 36 | + this.mediaServerItem = mediaServerItem; | |
| 37 | + } | |
| 38 | + | |
| 39 | + public String getCodec() { | |
| 40 | + return codec; | |
| 41 | + } | |
| 42 | + | |
| 43 | + public void setCodec(String codec) { | |
| 44 | + this.codec = codec; | |
| 45 | + } | |
| 46 | + | |
| 47 | + public String getApp() { | |
| 48 | + return app; | |
| 49 | + } | |
| 50 | + | |
| 51 | + public void setApp(String app) { | |
| 52 | + this.app = app; | |
| 53 | + } | |
| 54 | + | |
| 55 | + public String getStream() { | |
| 56 | + return stream; | |
| 57 | + } | |
| 58 | + | |
| 59 | + public void setStream(String stream) { | |
| 60 | + this.stream = stream; | |
| 61 | + } | |
| 62 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
| ... | ... | @@ -11,6 +11,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; |
| 11 | 11 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 12 | 12 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| 13 | 13 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 14 | +import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; | |
| 14 | 15 | import com.genersoft.iot.vmp.vmanager.bean.WVPResult; |
| 15 | 16 | import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; |
| 16 | 17 | import com.genersoft.iot.vmp.service.IMediaService; |
| ... | ... | @@ -39,6 +40,9 @@ import org.springframework.web.context.request.async.DeferredResult; |
| 39 | 40 | import java.util.List; |
| 40 | 41 | import java.util.UUID; |
| 41 | 42 | |
| 43 | +/** | |
| 44 | + * @author lin | |
| 45 | + */ | |
| 42 | 46 | @Api(tags = "国标设备点播") |
| 43 | 47 | @CrossOrigin |
| 44 | 48 | @RestController |
| ... | ... | @@ -102,7 +106,7 @@ public class PlayController { |
| 102 | 106 | logger.debug(String.format("设备预览/回放停止API调用,streamId:%s_%s", deviceId, channelId )); |
| 103 | 107 | |
| 104 | 108 | String uuid = UUID.randomUUID().toString(); |
| 105 | - DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(); | |
| 109 | + DeferredResult<ResponseEntity<String>> result = new DeferredResult<>(); | |
| 106 | 110 | |
| 107 | 111 | // 录像查询以channelId作为deviceId查询 |
| 108 | 112 | String key = DeferredResultHolder.CALLBACK_CMD_STOP + deviceId + channelId; |
| ... | ... | @@ -123,7 +127,7 @@ public class PlayController { |
| 123 | 127 | RequestMessage msgForSuccess = new RequestMessage(); |
| 124 | 128 | msgForSuccess.setId(uuid); |
| 125 | 129 | msgForSuccess.setKey(key); |
| 126 | - msgForSuccess.setData(String.format("success")); | |
| 130 | + msgForSuccess.setData("success"); | |
| 127 | 131 | resultHolder.invokeAllResult(msgForSuccess); |
| 128 | 132 | }); |
| 129 | 133 | |
| ... | ... | @@ -251,81 +255,73 @@ public class PlayController { |
| 251 | 255 | @ApiOperation("语音广播命令") |
| 252 | 256 | @ApiImplicitParams({ |
| 253 | 257 | @ApiImplicitParam(name = "deviceId", value = "设备Id", dataTypeClass = String.class), |
| 254 | - @ApiImplicitParam(name = "channelForSend", value = "设备用于发送语音数据的通道", dataTypeClass = String.class), | |
| 255 | - @ApiImplicitParam(name = "channelForReceive", value = "设备用于接收语音数据的通道", dataTypeClass = String.class), | |
| 258 | + @ApiImplicitParam(name = "channelId", value = "通道Id", dataTypeClass = String.class), | |
| 259 | + @ApiImplicitParam(name = "timeout", value = "推流超时时间(秒)", dataTypeClass = Integer.class), | |
| 256 | 260 | }) |
| 257 | - @GetMapping("/broadcast/{deviceId}") | |
| 258 | - @PostMapping("/broadcast/{deviceId}") | |
| 259 | - public DeferredResult<ResponseEntity<String>> broadcastApi(@PathVariable String deviceId, | |
| 260 | - String channelForSend, | |
| 261 | - String channelForReceive) { | |
| 261 | + @GetMapping("/broadcast/{deviceId}/{channelId}") | |
| 262 | + @PostMapping("/broadcast/{deviceId}/{channelId}") | |
| 263 | + public DeferredResult<WVPResult<AudioBroadcastResult>> broadcastApi(@PathVariable String deviceId, @PathVariable String channelId, Integer timeout) { | |
| 262 | 264 | if (logger.isDebugEnabled()) { |
| 263 | 265 | logger.debug("语音广播API调用"); |
| 264 | 266 | } |
| 265 | 267 | Device device = storager.queryVideoDevice(deviceId); |
| 266 | - DeferredResult<ResponseEntity<String>> result = new DeferredResult<>(3 * 1000L); | |
| 267 | - String key = DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId; | |
| 268 | - if (resultHolder.exist(key, null)) { | |
| 269 | - result.setResult(new ResponseEntity<>("设备使用中",HttpStatus.OK)); | |
| 270 | - return result; | |
| 268 | + if (device == null) { | |
| 269 | + WVPResult<AudioBroadcastResult> result = new WVPResult<>(); | |
| 270 | + result.setCode(-1); | |
| 271 | + result.setMsg("未找到设备: " + deviceId); | |
| 272 | + DeferredResult<WVPResult<AudioBroadcastResult>> deferredResult = new DeferredResult<>(); | |
| 273 | + deferredResult.setResult(result); | |
| 274 | + return deferredResult; | |
| 275 | + } | |
| 276 | + if (channelId == null) { | |
| 277 | + WVPResult<AudioBroadcastResult> result = new WVPResult<>(); | |
| 278 | + result.setCode(-1); | |
| 279 | + result.setMsg("未找到通道: " + channelId); | |
| 280 | + DeferredResult<WVPResult<AudioBroadcastResult>> deferredResult = new DeferredResult<>(); | |
| 281 | + deferredResult.setResult(result); | |
| 282 | + return deferredResult; | |
| 271 | 283 | } |
| 272 | 284 | |
| 273 | -// playService.audioBroadcast(deviceId, channelForSend, channelForReceive); | |
| 274 | - | |
| 275 | - | |
| 276 | - | |
| 277 | - | |
| 278 | - | |
| 279 | - | |
| 280 | - String uuid = UUID.randomUUID().toString(); | |
| 281 | - if (device == null) { | |
| 282 | - | |
| 283 | - resultHolder.put(key, key, result); | |
| 284 | - RequestMessage msg = new RequestMessage(); | |
| 285 | - msg.setKey(key); | |
| 286 | - msg.setId(uuid); | |
| 287 | - JSONObject json = new JSONObject(); | |
| 288 | - json.put("DeviceID", deviceId); | |
| 289 | - json.put("CmdType", "Broadcast"); | |
| 290 | - json.put("Result", "Failed"); | |
| 291 | - json.put("Description", "Device 不存在"); | |
| 292 | - msg.setData(json); | |
| 293 | - resultHolder.invokeResult(msg); | |
| 294 | - return result; | |
| 285 | + String key = DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId; | |
| 286 | + if (resultHolder.exist(key, null)) { | |
| 287 | + WVPResult<AudioBroadcastResult> wvpResult = new WVPResult<>(); | |
| 288 | + wvpResult.setCode(-1); | |
| 289 | + wvpResult.setMsg("设备使用中"); | |
| 290 | + DeferredResult<WVPResult<AudioBroadcastResult>> deferredResult = new DeferredResult<>(); | |
| 291 | + deferredResult.setResult(wvpResult); | |
| 292 | + return deferredResult; | |
| 295 | 293 | } |
| 296 | - cmder.audioBroadcastCmd(device, (event) -> { | |
| 297 | - RequestMessage msg = new RequestMessage(); | |
| 298 | - msg.setKey(key); | |
| 299 | - msg.setId(uuid); | |
| 300 | - JSONObject json = new JSONObject(); | |
| 301 | - json.put("DeviceID", deviceId); | |
| 302 | - json.put("CmdType", "Broadcast"); | |
| 303 | - json.put("Result", "Failed"); | |
| 304 | - json.put("Description", String.format("语音广播操作失败,错误码: %s, %s", event.statusCode, event.msg)); | |
| 305 | - msg.setData(json); | |
| 306 | - resultHolder.invokeResult(msg); | |
| 294 | + if (timeout == null){ | |
| 295 | + timeout = 30; | |
| 296 | + } | |
| 297 | + DeferredResult<WVPResult<AudioBroadcastResult>> result = new DeferredResult<>(timeout.longValue()*1000 + 2000); | |
| 298 | + String uuid = UUID.randomUUID().toString(); | |
| 299 | + result.onTimeout(()->{ | |
| 300 | + WVPResult<AudioBroadcastResult> wvpResult = new WVPResult<>(); | |
| 301 | + wvpResult.setCode(-1); | |
| 302 | + wvpResult.setMsg("请求超时"); | |
| 303 | + RequestMessage requestMessage = new RequestMessage(); | |
| 304 | + requestMessage.setKey(key); | |
| 305 | + requestMessage.setData(wvpResult); | |
| 306 | + resultHolder.invokeAllResult(requestMessage); | |
| 307 | 307 | }); |
| 308 | - | |
| 309 | - result.onTimeout(() -> { | |
| 310 | - logger.warn(String.format("语音广播操作超时, 设备未返回应答指令")); | |
| 311 | - RequestMessage msg = new RequestMessage(); | |
| 312 | - msg.setKey(key); | |
| 313 | - msg.setId(uuid); | |
| 314 | - JSONObject json = new JSONObject(); | |
| 315 | - json.put("DeviceID", deviceId); | |
| 316 | - json.put("CmdType", "Broadcast"); | |
| 317 | - json.put("Result", "Failed"); | |
| 318 | - json.put("Error", "Timeout. Device did not response to broadcast command."); | |
| 319 | - msg.setData(json); | |
| 320 | - resultHolder.invokeResult(msg); | |
| 308 | + playService.audioBroadcast(device, channelId, timeout, (msg)->{ | |
| 309 | + WVPResult<AudioBroadcastResult> wvpResult = new WVPResult<>(); | |
| 310 | + wvpResult.setCode(-1); | |
| 311 | + wvpResult.setMsg(msg); | |
| 312 | + RequestMessage requestMessage = new RequestMessage(); | |
| 313 | + requestMessage.setKey(key); | |
| 314 | + requestMessage.setData(wvpResult); | |
| 315 | + resultHolder.invokeAllResult(requestMessage); | |
| 321 | 316 | }); |
| 322 | 317 | resultHolder.put(key, uuid, result); |
| 318 | + | |
| 323 | 319 | return result; |
| 324 | 320 | } |
| 325 | 321 | |
| 326 | 322 | @ApiOperation("获取所有的ssrc") |
| 327 | 323 | @GetMapping("/ssrc") |
| 328 | - public WVPResult<JSONObject> getSSRC() { | |
| 324 | + public WVPResult<JSONObject> getSsrc() { | |
| 329 | 325 | if (logger.isDebugEnabled()) { |
| 330 | 326 | logger.debug("获取所有的ssrc"); |
| 331 | 327 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/bean/AudioBroadcastEvent.java
0 → 100644
web_src/src/components/dialog/deviceEdit.vue
| ... | ... | @@ -37,9 +37,6 @@ |
| 37 | 37 | </el-select> |
| 38 | 38 | </el-form-item> |
| 39 | 39 | <el-form-item label="语音发送通道" prop="name"> |
| 40 | - <el-input v-model="form.audioChannelForSend" clearable></el-input> | |
| 41 | - </el-form-item> | |
| 42 | - <el-form-item label="语音接收送通道" prop="name"> | |
| 43 | 40 | <el-input v-model="form.audioChannelForReceive" clearable></el-input> |
| 44 | 41 | </el-form-item> |
| 45 | 42 | <el-form-item label="目录订阅" title="0为取消订阅" prop="subscribeCycleForCatalog" > |
| ... | ... | @@ -105,6 +102,8 @@ export default { |
| 105 | 102 | }) |
| 106 | 103 | }, |
| 107 | 104 | onSubmit: function () { |
| 105 | + console.log("onSubmit"); | |
| 106 | + console.log(this.form); | |
| 108 | 107 | this.form.subscribeCycleForCatalog = this.form.subscribeCycleForCatalog||0 |
| 109 | 108 | this.form.subscribeCycleForMobilePosition = this.form.subscribeCycleForMobilePosition||0 |
| 110 | 109 | this.form.mobilePositionSubmissionInterval = this.form.mobilePositionSubmissionInterval||0 |
| ... | ... | @@ -124,7 +123,7 @@ export default { |
| 124 | 123 | }); |
| 125 | 124 | } |
| 126 | 125 | }).catch(function (error) { |
| 127 | - console.error(error); | |
| 126 | + console.log(error); | |
| 128 | 127 | }); |
| 129 | 128 | }, |
| 130 | 129 | close: function () { | ... | ... |