Commit 1d1f1748521930515fdab58e767c410d26108959
1 parent
26739237
合并主线
Showing
6 changed files
with
285 additions
and
279 deletions
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
| @@ -4,7 +4,6 @@ import com.genersoft.iot.vmp.gb28181.bean.*; | @@ -4,7 +4,6 @@ import com.genersoft.iot.vmp.gb28181.bean.*; | ||
| 4 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | 4 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| 5 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; | 5 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; |
| 6 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderPlarformProvider; | 6 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderPlarformProvider; |
| 7 | -import com.genersoft.iot.vmp.utils.DateUtil; | ||
| 8 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; | 7 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
| 9 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | 8 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 10 | import com.genersoft.iot.vmp.service.IMediaServerService; | 9 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| @@ -26,12 +25,13 @@ import org.springframework.lang.Nullable; | @@ -26,12 +25,13 @@ import org.springframework.lang.Nullable; | ||
| 26 | import org.springframework.stereotype.Component; | 25 | import org.springframework.stereotype.Component; |
| 27 | import org.springframework.util.StringUtils; | 26 | import org.springframework.util.StringUtils; |
| 28 | 27 | ||
| 28 | + | ||
| 29 | +import com.genersoft.iot.vmp.utils.DateUtil; | ||
| 29 | import javax.sip.*; | 30 | import javax.sip.*; |
| 30 | import javax.sip.address.SipURI; | 31 | import javax.sip.address.SipURI; |
| 31 | import javax.sip.header.*; | 32 | import javax.sip.header.*; |
| 32 | import javax.sip.message.Request; | 33 | import javax.sip.message.Request; |
| 33 | import java.lang.reflect.Field; | 34 | import java.lang.reflect.Field; |
| 34 | -import java.net.InetAddress; | ||
| 35 | import java.text.ParseException; | 35 | import java.text.ParseException; |
| 36 | import java.util.ArrayList; | 36 | import java.util.ArrayList; |
| 37 | import java.util.HashSet; | 37 | import java.util.HashSet; |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
| 1 | package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; | 1 | package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; |
| 2 | 2 | ||
| 3 | -import com.alibaba.fastjson.JSON; | ||
| 4 | import com.alibaba.fastjson.JSONObject; | 3 | import com.alibaba.fastjson.JSONObject; |
| 5 | -import com.genersoft.iot.vmp.common.StreamInfo; | ||
| 6 | import com.genersoft.iot.vmp.conf.DynamicTask; | 4 | import com.genersoft.iot.vmp.conf.DynamicTask; |
| 7 | import com.genersoft.iot.vmp.gb28181.bean.*; | 5 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 8 | import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; | 6 | import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; |
| @@ -22,7 +20,6 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | @@ -22,7 +20,6 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | ||
| 22 | import gov.nist.javax.sip.message.SIPRequest; | 20 | import gov.nist.javax.sip.message.SIPRequest; |
| 23 | import gov.nist.javax.sip.stack.SIPDialog; | 21 | import gov.nist.javax.sip.stack.SIPDialog; |
| 24 | import com.genersoft.iot.vmp.utils.SerializeUtils; | 22 | import com.genersoft.iot.vmp.utils.SerializeUtils; |
| 25 | -import org.ehcache.shadow.org.terracotta.offheapstore.storage.IntegerStorageEngine; | ||
| 26 | import org.slf4j.Logger; | 23 | import org.slf4j.Logger; |
| 27 | import org.slf4j.LoggerFactory; | 24 | import org.slf4j.LoggerFactory; |
| 28 | import org.springframework.beans.factory.InitializingBean; | 25 | import org.springframework.beans.factory.InitializingBean; |
| @@ -37,7 +34,6 @@ import javax.sip.address.SipURI; | @@ -37,7 +34,6 @@ import javax.sip.address.SipURI; | ||
| 37 | import javax.sip.header.CallIdHeader; | 34 | import javax.sip.header.CallIdHeader; |
| 38 | import javax.sip.header.FromHeader; | 35 | import javax.sip.header.FromHeader; |
| 39 | import javax.sip.header.HeaderAddress; | 36 | import javax.sip.header.HeaderAddress; |
| 40 | -import javax.sip.header.ToHeader; | ||
| 41 | import java.text.ParseException; | 37 | import java.text.ParseException; |
| 42 | import java.util.*; | 38 | import java.util.*; |
| 43 | 39 | ||
| @@ -99,28 +95,28 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In | @@ -99,28 +95,28 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In | ||
| 99 | @Override | 95 | @Override |
| 100 | public void process(RequestEvent evt) { | 96 | public void process(RequestEvent evt) { |
| 101 | Dialog dialog = evt.getDialog(); | 97 | Dialog dialog = evt.getDialog(); |
| 102 | - CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME); | 98 | + CallIdHeader callIdHeader = (CallIdHeader) evt.getRequest().getHeader(CallIdHeader.NAME); |
| 103 | if (dialog == null) { | 99 | if (dialog == null) { |
| 104 | return; | 100 | return; |
| 105 | } | 101 | } |
| 106 | - if (dialog.getState()== DialogState.CONFIRMED) { | 102 | + if (dialog.getState() == DialogState.CONFIRMED) { |
| 107 | String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); | 103 | String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); |
| 108 | logger.info("ACK请求: platformGbId->{}", platformGbId); | 104 | logger.info("ACK请求: platformGbId->{}", platformGbId); |
| 109 | ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformGbId); | 105 | ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformGbId); |
| 110 | // 取消设置的超时任务 | 106 | // 取消设置的超时任务 |
| 111 | dynamicTask.stop(callIdHeader.getCallId()); | 107 | dynamicTask.stop(callIdHeader.getCallId()); |
| 112 | // String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); | 108 | // String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); |
| 113 | - SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, null, null, callIdHeader.getCallId()); | 109 | + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, null, null, callIdHeader.getCallId()); |
| 114 | String is_Udp = sendRtpItem.isTcp() ? "0" : "1"; | 110 | String is_Udp = sendRtpItem.isTcp() ? "0" : "1"; |
| 115 | MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | 111 | MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); |
| 116 | logger.info("[收到ACK],开始使用{}向上级推流 {}/{}->{}:{}({})", sendRtpItem.isTcp() ? "TCP" : "UDP", | 112 | logger.info("[收到ACK],开始使用{}向上级推流 {}/{}->{}:{}({})", sendRtpItem.isTcp() ? "TCP" : "UDP", |
| 117 | sendRtpItem.getApp(), sendRtpItem.getStreamId(), | 113 | sendRtpItem.getApp(), sendRtpItem.getStreamId(), |
| 118 | - sendRtpItem.getIp() ,sendRtpItem.getPort(), | 114 | + sendRtpItem.getIp(), sendRtpItem.getPort(), |
| 119 | sendRtpItem.getSsrc()); | 115 | sendRtpItem.getSsrc()); |
| 120 | Map<String, Object> param = new HashMap<>(); | 116 | Map<String, Object> param = new HashMap<>(); |
| 121 | - param.put("vhost","__defaultVhost__"); | ||
| 122 | - param.put("app",sendRtpItem.getApp()); | ||
| 123 | - param.put("stream",sendRtpItem.getStreamId()); | 117 | + param.put("vhost", "__defaultVhost__"); |
| 118 | + param.put("app", sendRtpItem.getApp()); | ||
| 119 | + param.put("stream", sendRtpItem.getStreamId()); | ||
| 124 | param.put("ssrc", sendRtpItem.getSsrc()); | 120 | param.put("ssrc", sendRtpItem.getSsrc()); |
| 125 | param.put("src_port", sendRtpItem.getLocalPort()); | 121 | param.put("src_port", sendRtpItem.getLocalPort()); |
| 126 | param.put("pt", sendRtpItem.getPt()); | 122 | param.put("pt", sendRtpItem.getPt()); |
| @@ -129,9 +125,9 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In | @@ -129,9 +125,9 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In | ||
| 129 | JSONObject jsonObject; | 125 | JSONObject jsonObject; |
| 130 | if (sendRtpItem.isTcpActive()) { | 126 | if (sendRtpItem.isTcpActive()) { |
| 131 | jsonObject = zlmrtpServerFactory.startSendRtpPassive(mediaInfo, param); | 127 | jsonObject = zlmrtpServerFactory.startSendRtpPassive(mediaInfo, param); |
| 132 | - }else { | 128 | + } else { |
| 133 | param.put("is_udp", is_Udp); | 129 | param.put("is_udp", is_Udp); |
| 134 | - param.put("dst_url",sendRtpItem.getIp()); | 130 | + param.put("dst_url", sendRtpItem.getIp()); |
| 135 | param.put("dst_port", sendRtpItem.getPort()); | 131 | param.put("dst_port", sendRtpItem.getPort()); |
| 136 | jsonObject = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); | 132 | jsonObject = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); |
| 137 | } | 133 | } |
| @@ -149,36 +145,37 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In | @@ -149,36 +145,37 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In | ||
| 149 | String waiteStreamTimeoutTaskKey = "waite-stream-" + audioBroadcastCatch.getDeviceId() + audioBroadcastCatch.getChannelId(); | 145 | String waiteStreamTimeoutTaskKey = "waite-stream-" + audioBroadcastCatch.getDeviceId() + audioBroadcastCatch.getChannelId(); |
| 150 | dynamicTask.stop(waiteStreamTimeoutTaskKey); | 146 | dynamicTask.stop(waiteStreamTimeoutTaskKey); |
| 151 | } | 147 | } |
| 152 | - logger.info("RTP推流成功[ {}/{} ],{}->{}:{}, " ,param.get("app"), param.get("stream"), jsonObject.getString("local_port"), param.get("dst_url"), param.get("dst_port")); | 148 | + logger.info("RTP推流成功[ {}/{} ],{}->{}:{}, ", param.get("app"), param.get("stream"), jsonObject.getString("local_port"), param.get("dst_url"), param.get("dst_port")); |
| 153 | } else { | 149 | } else { |
| 154 | - logger.error("RTP推流失败: {}, 参数:{}",jsonObject.getString("msg"),JSONObject.toJSON(param)); | 150 | + logger.error("RTP推流失败: {}, 参数:{}", jsonObject.getString("msg"), JSONObject.toJSON(param)); |
| 155 | if (sendRtpItem.isOnlyAudio()) { | 151 | if (sendRtpItem.isOnlyAudio()) { |
| 156 | // 语音对讲 | 152 | // 语音对讲 |
| 157 | try { | 153 | try { |
| 158 | - cmder.streamByeCmd((SIPDialog) evt.getDialog(), (SIPRequest)evt.getRequest(), null); | 154 | + cmder.streamByeCmd((SIPDialog) evt.getDialog(), (SIPRequest) evt.getRequest(), null); |
| 159 | } catch (SipException e) { | 155 | } catch (SipException e) { |
| 160 | throw new RuntimeException(e); | 156 | throw new RuntimeException(e); |
| 161 | } catch (ParseException e) { | 157 | } catch (ParseException e) { |
| 162 | throw new RuntimeException(e); | 158 | throw new RuntimeException(e); |
| 163 | } | 159 | } |
| 164 | - }else { | 160 | + } else { |
| 165 | // 向上级平台 | 161 | // 向上级平台 |
| 166 | commanderForPlatform.streamByeCmd(parentPlatform, callIdHeader.getCallId()); | 162 | commanderForPlatform.streamByeCmd(parentPlatform, callIdHeader.getCallId()); |
| 167 | } | 163 | } |
| 168 | - if (mediaInfo == null) { | ||
| 169 | - RequestPushStreamMsg requestPushStreamMsg = RequestPushStreamMsg.getInstance( | ||
| 170 | - sendRtpItem.getMediaServerId(), sendRtpItem.getApp(), sendRtpItem.getStreamId(), | ||
| 171 | - sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isTcp(), | ||
| 172 | - sendRtpItem.getLocalPort(), sendRtpItem.getPt(), sendRtpItem.isUsePs(), sendRtpItem.isOnlyAudio()); | ||
| 173 | - redisGbPlayMsgListener.sendMsgForStartSendRtpStream(sendRtpItem.getServerId(), requestPushStreamMsg, jsonObject->{ | ||
| 174 | - startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, jsonObject, param, callIdHeader); | ||
| 175 | - }); | ||
| 176 | - }else { | ||
| 177 | - JSONObject jsonObject = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); | ||
| 178 | - startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, jsonObject, param, callIdHeader); | ||
| 179 | - } | 164 | + if (mediaInfo == null) { |
| 165 | + RequestPushStreamMsg requestPushStreamMsg = RequestPushStreamMsg.getInstance( | ||
| 166 | + sendRtpItem.getMediaServerId(), sendRtpItem.getApp(), sendRtpItem.getStreamId(), | ||
| 167 | + sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isTcp(), | ||
| 168 | + sendRtpItem.getLocalPort(), sendRtpItem.getPt(), sendRtpItem.isUsePs(), sendRtpItem.isOnlyAudio()); | ||
| 169 | + redisGbPlayMsgListener.sendMsgForStartSendRtpStream(sendRtpItem.getServerId(), requestPushStreamMsg, json -> { | ||
| 170 | + startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, json, param, callIdHeader); | ||
| 171 | + }); | ||
| 172 | + } else { | ||
| 173 | + JSONObject startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); | ||
| 174 | + startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, startSendRtpStreamResult, param, callIdHeader); | ||
| 175 | + } | ||
| 180 | 176 | ||
| 181 | 177 | ||
| 178 | + } | ||
| 182 | } | 179 | } |
| 183 | } | 180 | } |
| 184 | private void startSendRtpStreamHand(RequestEvent evt, SendRtpItem sendRtpItem, ParentPlatform parentPlatform, | 181 | private void startSendRtpStreamHand(RequestEvent evt, SendRtpItem sendRtpItem, ParentPlatform parentPlatform, |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
| @@ -19,15 +19,14 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; | @@ -19,15 +19,14 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; | ||
| 19 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; | 19 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; |
| 20 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; | 20 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
| 21 | import com.genersoft.iot.vmp.gb28181.utils.SipUtils; | 21 | import com.genersoft.iot.vmp.gb28181.utils.SipUtils; |
| 22 | -import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; | ||
| 23 | import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; | 22 | import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; |
| 24 | import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager; | 23 | import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager; |
| 25 | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; | 24 | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; |
| 26 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; | 25 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
| 27 | import com.genersoft.iot.vmp.media.zlm.dto.MediaItem; | 26 | import com.genersoft.iot.vmp.media.zlm.dto.MediaItem; |
| 28 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | 27 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 29 | -import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; | ||
| 30 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItemLite; | 28 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItemLite; |
| 29 | +import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; | ||
| 31 | import com.genersoft.iot.vmp.service.IMediaServerService; | 30 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| 32 | import com.genersoft.iot.vmp.service.IPlayService; | 31 | import com.genersoft.iot.vmp.service.IPlayService; |
| 33 | import com.genersoft.iot.vmp.service.IStreamPushService; | 32 | import com.genersoft.iot.vmp.service.IStreamPushService; |
| @@ -58,8 +57,6 @@ import javax.sip.message.Request; | @@ -58,8 +57,6 @@ import javax.sip.message.Request; | ||
| 58 | import javax.sip.message.Response; | 57 | import javax.sip.message.Response; |
| 59 | import java.text.ParseException; | 58 | import java.text.ParseException; |
| 60 | import java.time.Instant; | 59 | import java.time.Instant; |
| 61 | -import java.util.Date; | ||
| 62 | -import java.util.List; | ||
| 63 | import java.util.Vector; | 60 | import java.util.Vector; |
| 64 | 61 | ||
| 65 | /** | 62 | /** |
| @@ -109,9 +106,6 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -109,9 +106,6 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 109 | @Autowired | 106 | @Autowired |
| 110 | private ZLMRESTfulUtils zlmresTfulUtils; | 107 | private ZLMRESTfulUtils zlmresTfulUtils; |
| 111 | 108 | ||
| 112 | - @Autowired | ||
| 113 | - private IMediaServerService mediaServerService; | ||
| 114 | - | ||
| 115 | @Autowired | 109 | @Autowired |
| 116 | private SIPProcessorObserver sipProcessorObserver; | 110 | private SIPProcessorObserver sipProcessorObserver; |
| 117 | 111 | ||
| @@ -171,7 +165,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -171,7 +165,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 171 | // 查询请求是否来自上级平台\设备 | 165 | // 查询请求是否来自上级平台\设备 |
| 172 | ParentPlatform platform = storager.queryParentPlatByServerGBId(requesterId); | 166 | ParentPlatform platform = storager.queryParentPlatByServerGBId(requesterId); |
| 173 | if (platform == null) { | 167 | if (platform == null) { |
| 174 | - inviteFromDeviceHandle(evt, requesterId); | 168 | + inviteFromDeviceHandle(evt, requesterId, channelId); |
| 175 | } else { | 169 | } else { |
| 176 | // 查询平台下是否有该通道 | 170 | // 查询平台下是否有该通道 |
| 177 | DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId); | 171 | DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId); |
| @@ -724,10 +718,16 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -724,10 +718,16 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 724 | } | 718 | } |
| 725 | } | 719 | } |
| 726 | 720 | ||
| 727 | - public void inviteFromDeviceHandle(RequestEvent evt, String requesterId) throws InvalidArgumentException, ParseException, SipException, SdpException { | 721 | + public void inviteFromDeviceHandle(RequestEvent evt, String requesterId, String channelId1) throws InvalidArgumentException, ParseException, SipException, SdpException { |
| 728 | 722 | ||
| 729 | // 非上级平台请求,查询是否设备请求(通常为接收语音广播的设备) | 723 | // 非上级平台请求,查询是否设备请求(通常为接收语音广播的设备) |
| 730 | Device device = redisCatchStorage.getDevice(requesterId); | 724 | Device device = redisCatchStorage.getDevice(requesterId); |
| 725 | + AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(requesterId, channelId1); | ||
| 726 | + if (audioBroadcastCatch == null) { | ||
| 727 | + logger.warn("来自设备的Invite请求非语音广播,已忽略"); | ||
| 728 | + responseAck(evt, Response.FORBIDDEN); | ||
| 729 | + return; | ||
| 730 | + } | ||
| 731 | Request request = evt.getRequest(); | 731 | Request request = evt.getRequest(); |
| 732 | if (device != null) { | 732 | if (device != null) { |
| 733 | logger.info("收到设备" + requesterId + "的语音广播Invite请求"); | 733 | logger.info("收到设备" + requesterId + "的语音广播Invite请求"); |
| @@ -740,7 +740,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -740,7 +740,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 740 | int ssrcIndex = contentString.indexOf("y="); | 740 | int ssrcIndex = contentString.indexOf("y="); |
| 741 | if (ssrcIndex > 0) { | 741 | if (ssrcIndex > 0) { |
| 742 | substring = contentString.substring(0, ssrcIndex); | 742 | substring = contentString.substring(0, ssrcIndex); |
| 743 | - ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); | 743 | + ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12).trim(); |
| 744 | } | 744 | } |
| 745 | ssrcIndex = substring.indexOf("f="); | 745 | ssrcIndex = substring.indexOf("f="); |
| 746 | if (ssrcIndex > 0) { | 746 | if (ssrcIndex > 0) { |
| @@ -750,13 +750,13 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -750,13 +750,13 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 750 | 750 | ||
| 751 | // 获取支持的格式 | 751 | // 获取支持的格式 |
| 752 | Vector mediaDescriptions = sdp.getMediaDescriptions(true); | 752 | Vector mediaDescriptions = sdp.getMediaDescriptions(true); |
| 753 | + | ||
| 753 | // 查看是否支持PS 负载96 | 754 | // 查看是否支持PS 负载96 |
| 754 | int port = -1; | 755 | int port = -1; |
| 755 | - //boolean recvonly = false; | ||
| 756 | boolean mediaTransmissionTCP = false; | 756 | boolean mediaTransmissionTCP = false; |
| 757 | Boolean tcpActive = null; | 757 | Boolean tcpActive = null; |
| 758 | for (int i = 0; i < mediaDescriptions.size(); i++) { | 758 | for (int i = 0; i < mediaDescriptions.size(); i++) { |
| 759 | - MediaDescription mediaDescription = (MediaDescription) mediaDescriptions.get(i); | 759 | + MediaDescription mediaDescription = (MediaDescription)mediaDescriptions.get(i); |
| 760 | Media media = mediaDescription.getMedia(); | 760 | Media media = mediaDescription.getMedia(); |
| 761 | 761 | ||
| 762 | Vector mediaFormats = media.getMediaFormats(false); | 762 | Vector mediaFormats = media.getMediaFormats(false); |
| @@ -784,233 +784,248 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -784,233 +784,248 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 784 | responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415 | 784 | responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415 |
| 785 | return; | 785 | return; |
| 786 | } | 786 | } |
| 787 | - String username = sdp.getOrigin().getUsername(); | ||
| 788 | String addressStr = sdp.getOrigin().getAddress(); | 787 | String addressStr = sdp.getOrigin().getAddress(); |
| 789 | - logger.info("设备{}请求语音流,地址:{}:{},ssrc:{}", username, addressStr, port, ssrc); | 788 | + logger.info("设备{}请求语音流,地址:{}:{},ssrc:{}", requesterId, addressStr, port, ssrc); |
| 789 | + | ||
| 790 | + MediaServerItem mediaServerItem = playService.getNewMediaServerItem(device); | ||
| 791 | + if (mediaServerItem == null) { | ||
| 792 | + logger.warn("未找到可用的zlm"); | ||
| 793 | + responseAck(evt, Response.BUSY_HERE); | ||
| 794 | + return; | ||
| 795 | + } | ||
| 796 | + SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, | ||
| 797 | + device.getDeviceId(), audioBroadcastCatch.getChannelId(), | ||
| 798 | + mediaTransmissionTCP); | ||
| 799 | + if (sendRtpItem == null) { | ||
| 800 | + logger.warn("服务器端口资源不足"); | ||
| 801 | + responseAck(evt, Response.BUSY_HERE); | ||
| 802 | + return; | ||
| 803 | + } | ||
| 804 | + sendRtpItem.setTcp(mediaTransmissionTCP); | ||
| 805 | + if (tcpActive != null) { | ||
| 806 | + sendRtpItem.setTcpActive(tcpActive); | ||
| 807 | + } | ||
| 808 | + String app = "broadcast"; | ||
| 809 | + String stream = device.getDeviceId() + "_" + audioBroadcastCatch.getChannelId(); | ||
| 810 | + | ||
| 811 | + CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME); | ||
| 812 | + sendRtpItem.setPlayType(InviteStreamType.PLAY); | ||
| 813 | + sendRtpItem.setCallId(callIdHeader.getCallId()); | ||
| 814 | + sendRtpItem.setPlatformId(requesterId); | ||
| 815 | + sendRtpItem.setStatus(1); | ||
| 816 | + sendRtpItem.setApp(app); | ||
| 817 | + sendRtpItem.setStreamId(stream); | ||
| 818 | + sendRtpItem.setPt(8); | ||
| 819 | + sendRtpItem.setUsePs(false); | ||
| 820 | + sendRtpItem.setOnlyAudio(true); | ||
| 821 | + redisCatchStorage.updateSendRTPSever(sendRtpItem); | ||
| 822 | + | ||
| 823 | + // hook监听等待设备推流上来 | ||
| 824 | + // 添加订阅 | ||
| 825 | + JSONObject subscribeKey = new JSONObject(); | ||
| 826 | + subscribeKey.put("app", app); | ||
| 827 | + subscribeKey.put("stream", stream); | ||
| 828 | + subscribeKey.put("regist", true); | ||
| 829 | + subscribeKey.put("schema", "rtmp"); | ||
| 830 | + subscribeKey.put("mediaServerId", mediaServerItem.getId()); | ||
| 831 | + String finalSsrc = ssrc; | ||
| 832 | + // 流已经存在时直接推流 | ||
| 833 | + JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtsp", stream); | ||
| 834 | + JSONArray tracks = mediaInfo.getJSONArray("tracks"); | ||
| 835 | + Integer codecId = null; | ||
| 836 | + if (tracks != null && tracks.size() > 0) { | ||
| 837 | + for (int i = 0; i < tracks.size(); i++) { | ||
| 838 | + MediaItem.MediaTrack track = JSON.toJavaObject((JSON)tracks.get(i),MediaItem.MediaTrack.class); | ||
| 839 | + if (track.getCodecType() == 1) { | ||
| 840 | + codecId = track.getCodecId(); | ||
| 841 | + break; | ||
| 842 | + } | ||
| 843 | + } | ||
| 844 | + } | ||
| 845 | + if ((mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online"))) { | ||
| 846 | + logger.info("发现已经在推流"); | ||
| 847 | + sendRtpItem.setStatus(2); | ||
| 848 | + redisCatchStorage.updateSendRTPSever(sendRtpItem); | ||
| 849 | + StringBuffer content = new StringBuffer(200); | ||
| 850 | + content.append("v=0\r\n"); | ||
| 851 | + content.append("o="+ config.getId() +" "+ sdp.getOrigin().getSessionId() +" " + sdp.getOrigin().getSessionVersion() + " IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); | ||
| 852 | + content.append("s=Play\r\n"); | ||
| 853 | + content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); | ||
| 854 | + content.append("t=0 0\r\n"); | ||
| 855 | + if (codecId == null) { | ||
| 856 | + if (mediaTransmissionTCP) { | ||
| 857 | + content.append("m=audio "+ sendRtpItem.getLocalPort()+" TCP/RTP/AVP 8\r\n"); | ||
| 858 | + }else { | ||
| 859 | + content.append("m=audio "+ sendRtpItem.getLocalPort()+" RTP/AVP 8\r\n"); | ||
| 860 | + } | ||
| 861 | + | ||
| 862 | + content.append("a=rtpmap:8 PCMA/8000\r\n"); | ||
| 863 | + }else { | ||
| 864 | + if (codecId == 4) { | ||
| 865 | + if (mediaTransmissionTCP) { | ||
| 866 | + content.append("m=audio "+ sendRtpItem.getLocalPort()+" TCP/RTP/AVP 0\r\n"); | ||
| 867 | + }else { | ||
| 868 | + content.append("m=audio "+ sendRtpItem.getLocalPort()+" RTP/AVP 0\r\n"); | ||
| 869 | + } | ||
| 870 | + content.append("a=rtpmap:0 PCMU/8000\r\n"); | ||
| 871 | + }else { | ||
| 872 | + if (mediaTransmissionTCP) { | ||
| 873 | + content.append("m=audio "+ sendRtpItem.getLocalPort()+" TCP/RTP/AVP 8\r\n"); | ||
| 874 | + }else { | ||
| 875 | + content.append("m=audio "+ sendRtpItem.getLocalPort()+" RTP/AVP 8\r\n"); | ||
| 876 | + } | ||
| 877 | + content.append("a=rtpmap:8 PCMA/8000\r\n"); | ||
| 878 | + } | ||
| 879 | + } | ||
| 880 | + if (sendRtpItem.isTcp()) { | ||
| 881 | + content.append("a=connection:new\r\n"); | ||
| 882 | + if (!sendRtpItem.isTcpActive()) { | ||
| 883 | + content.append("a=setup:active\r\n"); | ||
| 884 | + }else { | ||
| 885 | + content.append("a=setup:passive\r\n"); | ||
| 886 | + } | ||
| 887 | + } | ||
| 888 | + content.append("a=sendonly\r\n"); | ||
| 889 | + content.append("y="+ finalSsrc + "\r\n"); | ||
| 890 | + content.append("f=v/////a/1/8/1\r\n"); | ||
| 891 | + | ||
| 892 | + ParentPlatform parentPlatform = new ParentPlatform(); | ||
| 893 | + parentPlatform.setServerIP(device.getIp()); | ||
| 894 | + parentPlatform.setServerPort(device.getPort()); | ||
| 895 | + parentPlatform.setServerGBId(device.getDeviceId()); | ||
| 896 | + try { | ||
| 897 | + responseSdpAck(evt, content.toString(), parentPlatform); | ||
| 898 | + Dialog dialog = evt.getDialog(); | ||
| 899 | + audioBroadcastCatch.setDialog((SIPDialog) dialog); | ||
| 900 | + audioBroadcastCatch.setRequest((SIPRequest) request); | ||
| 901 | + audioBroadcastManager.update(audioBroadcastCatch); | ||
| 902 | + } catch (SipException e) { | ||
| 903 | + throw new RuntimeException(e); | ||
| 904 | + } catch (InvalidArgumentException e) { | ||
| 905 | + throw new RuntimeException(e); | ||
| 906 | + } catch (ParseException e) { | ||
| 907 | + throw new RuntimeException(e); | ||
| 908 | + } | ||
| 909 | + }else { | ||
| 910 | + // 流不存在时监听流上线 | ||
| 911 | + // 设置等待推流的超时; 默认20s | ||
| 912 | + String waiteStreamTimeoutTaskKey = "waite-stream-" + device.getDeviceId() + audioBroadcastCatch.getChannelId(); | ||
| 913 | + dynamicTask.startDelay(waiteStreamTimeoutTaskKey, ()->{ | ||
| 914 | + logger.info("等待推流超时: {}/{}", app, stream); | ||
| 915 | + subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey); | ||
| 916 | + playService.stopAudioBroadcast(device.getDeviceId(), audioBroadcastCatch.getChannelId()); | ||
| 917 | + // 发送bye | ||
| 918 | + try { | ||
| 919 | + responseAck(evt, Response.BUSY_HERE); | ||
| 920 | + } catch (SipException e) { | ||
| 921 | + throw new RuntimeException(e); | ||
| 922 | + } catch (InvalidArgumentException e) { | ||
| 923 | + throw new RuntimeException(e); | ||
| 924 | + } catch (ParseException e) { | ||
| 925 | + throw new RuntimeException(e); | ||
| 926 | + } | ||
| 927 | + }, 20*1000); | ||
| 928 | + | ||
| 929 | + boolean finalMediaTransmissionTCP = mediaTransmissionTCP; | ||
| 930 | + subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, | ||
| 931 | + (MediaServerItem mediaServerItemInUse, JSONObject json)->{ | ||
| 932 | + logger.info("收到语音对讲推流"); | ||
| 933 | + MediaItem mediaItem = JSON.toJavaObject(json, MediaItem.class); | ||
| 934 | + Integer audioCodecId = null; | ||
| 935 | + if (mediaItem.getTracks() != null && mediaItem.getTracks().size() > 0) { | ||
| 936 | + for (int i = 0; i < mediaItem.getTracks().size(); i++) { | ||
| 937 | + MediaItem.MediaTrack mediaTrack = mediaItem.getTracks().get(i); | ||
| 938 | + if (mediaTrack.getCodecType() == 1) { | ||
| 939 | + audioCodecId = mediaTrack.getCodecId(); | ||
| 940 | + break; | ||
| 941 | + } | ||
| 942 | + } | ||
| 943 | + } | ||
| 790 | 944 | ||
| 945 | + try { | ||
| 946 | + sendRtpItem.setStatus(2); | ||
| 947 | + redisCatchStorage.updateSendRTPSever(sendRtpItem); | ||
| 948 | + StringBuffer content = new StringBuffer(200); | ||
| 949 | + content.append("v=0\r\n"); | ||
| 950 | + content.append("o="+ config.getId() +" "+ sdp.getOrigin().getSessionId() +" " + sdp.getOrigin().getSessionVersion() + " IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); | ||
| 951 | + content.append("s=Play\r\n"); | ||
| 952 | + content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); | ||
| 953 | + content.append("t=0 0\r\n"); | ||
| 954 | + if (audioCodecId == null) { | ||
| 955 | + if (finalMediaTransmissionTCP) { | ||
| 956 | + content.append("m=audio "+ sendRtpItem.getLocalPort()+" TCP/RTP/AVP 8\r\n"); | ||
| 957 | + }else { | ||
| 958 | + content.append("m=audio "+ sendRtpItem.getLocalPort()+" RTP/AVP 8\r\n"); | ||
| 959 | + } | ||
| 960 | + | ||
| 961 | + content.append("a=rtpmap:8 PCMA/8000\r\n"); | ||
| 962 | + }else { | ||
| 963 | + if (audioCodecId == 4) { | ||
| 964 | + if (finalMediaTransmissionTCP) { | ||
| 965 | + content.append("m=audio "+ sendRtpItem.getLocalPort()+" TCP/RTP/AVP 0\r\n"); | ||
| 966 | + }else { | ||
| 967 | + content.append("m=audio "+ sendRtpItem.getLocalPort()+" RTP/AVP 0\r\n"); | ||
| 968 | + } | ||
| 969 | + content.append("a=rtpmap:0 PCMU/8000\r\n"); | ||
| 970 | + }else { | ||
| 971 | + if (finalMediaTransmissionTCP) { | ||
| 972 | + content.append("m=audio "+ sendRtpItem.getLocalPort()+" TCP/RTP/AVP 8\r\n"); | ||
| 973 | + }else { | ||
| 974 | + content.append("m=audio "+ sendRtpItem.getLocalPort()+" RTP/AVP 8\r\n"); | ||
| 975 | + } | ||
| 976 | + content.append("a=rtpmap:8 PCMA/8000\r\n"); | ||
| 977 | + } | ||
| 978 | + } | ||
| 979 | + content.append("a=sendonly\r\n"); | ||
| 980 | + if (sendRtpItem.isTcp()) { | ||
| 981 | + content.append("a=connection:new\r\n"); | ||
| 982 | + if (!sendRtpItem.isTcpActive()) { | ||
| 983 | + content.append("a=setup:active\r\n"); | ||
| 984 | + }else { | ||
| 985 | + content.append("a=setup:passive\r\n"); | ||
| 986 | + } | ||
| 987 | + } | ||
| 988 | + content.append("y="+ finalSsrc + "\r\n"); | ||
| 989 | + content.append("f=v/////a/1/8/1\r\n"); | ||
| 990 | + | ||
| 991 | + ParentPlatform parentPlatform = new ParentPlatform(); | ||
| 992 | + parentPlatform.setServerIP(device.getIp()); | ||
| 993 | + parentPlatform.setServerPort(device.getPort()); | ||
| 994 | + parentPlatform.setServerGBId(device.getDeviceId()); | ||
| 995 | + | ||
| 996 | + responseSdpAck(evt, content.toString(), parentPlatform); | ||
| 997 | + Dialog dialog = evt.getDialog(); | ||
| 998 | + audioBroadcastCatch.setDialog((SIPDialog) dialog); | ||
| 999 | + audioBroadcastCatch.setRequest((SIPRequest) request); | ||
| 1000 | + audioBroadcastManager.update(audioBroadcastCatch); | ||
| 1001 | + } catch (SipException e) { | ||
| 1002 | + throw new RuntimeException(e); | ||
| 1003 | + } catch (InvalidArgumentException e) { | ||
| 1004 | + throw new RuntimeException(e); | ||
| 1005 | + } catch (ParseException e) { | ||
| 1006 | + throw new RuntimeException(e); | ||
| 1007 | + } catch (SdpParseException e) { | ||
| 1008 | + throw new RuntimeException(e); | ||
| 1009 | + } | ||
| 1010 | + }); | ||
| 1011 | + } | ||
| 1012 | + String key = DeferredResultHolder.CALLBACK_CMD_BROADCAST + device.getDeviceId(); | ||
| 1013 | + WVPResult<AudioBroadcastResult> wvpResult = new WVPResult<>(); | ||
| 1014 | + wvpResult.setCode(0); | ||
| 1015 | + wvpResult.setMsg("success"); | ||
| 1016 | + AudioBroadcastResult audioBroadcastResult = new AudioBroadcastResult(); | ||
| 1017 | + audioBroadcastResult.setApp(app); | ||
| 1018 | + audioBroadcastResult.setStream(stream); | ||
| 1019 | + audioBroadcastResult.setMediaServerItem(new MediaServerItemLite(mediaServerItem)); | ||
| 1020 | + audioBroadcastResult.setCodec("G.711"); | ||
| 1021 | + wvpResult.setData(audioBroadcastResult); | ||
| 1022 | + RequestMessage requestMessage = new RequestMessage(); | ||
| 1023 | + requestMessage.setKey(key); | ||
| 1024 | + requestMessage.setData(wvpResult); | ||
| 1025 | + resultHolder.invokeAllResult(requestMessage); | ||
| 791 | } else { | 1026 | } else { |
| 792 | logger.warn("来自无效设备/平台的请求"); | 1027 | logger.warn("来自无效设备/平台的请求"); |
| 793 | responseAck(evt, Response.BAD_REQUEST); | 1028 | responseAck(evt, Response.BAD_REQUEST); |
| 794 | } | 1029 | } |
| 795 | } | 1030 | } |
| 796 | - CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME); | ||
| 797 | - sendRtpItem.setPlayType(InviteStreamType.PLAY); | ||
| 798 | - sendRtpItem.setCallId(callIdHeader.getCallId()); | ||
| 799 | - sendRtpItem.setPlatformId(requesterId); | ||
| 800 | - sendRtpItem.setStatus(1); | ||
| 801 | - sendRtpItem.setApp(app); | ||
| 802 | - sendRtpItem.setStreamId(stream); | ||
| 803 | - sendRtpItem.setPt(8); | ||
| 804 | - sendRtpItem.setUsePs(false); | ||
| 805 | - sendRtpItem.setOnlyAudio(true); | ||
| 806 | - redisCatchStorage.updateSendRTPSever(sendRtpItem); | ||
| 807 | - | ||
| 808 | - // hook监听等待设备推流上来 | ||
| 809 | - // 添加订阅 | ||
| 810 | - JSONObject subscribeKey = new JSONObject(); | ||
| 811 | - subscribeKey.put("app", app); | ||
| 812 | - subscribeKey.put("stream", stream); | ||
| 813 | - subscribeKey.put("regist", true); | ||
| 814 | - subscribeKey.put("schema", "rtmp"); | ||
| 815 | - subscribeKey.put("mediaServerId", mediaServerItem.getId()); | ||
| 816 | - String finalSsrc = ssrc; | ||
| 817 | - // 流已经存在时直接推流 | ||
| 818 | - JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtsp", stream); | ||
| 819 | - JSONArray tracks = mediaInfo.getJSONArray("tracks"); | ||
| 820 | - Integer codecId = null; | ||
| 821 | - if (tracks != null && tracks.size() > 0) { | ||
| 822 | - for (int i = 0; i < tracks.size(); i++) { | ||
| 823 | - MediaItem.MediaTrack track = JSON.toJavaObject((JSON)tracks.get(i),MediaItem.MediaTrack.class); | ||
| 824 | - if (track.getCodecType() == 1) { | ||
| 825 | - codecId = track.getCodecId(); | ||
| 826 | - break; | ||
| 827 | - } | ||
| 828 | - } | ||
| 829 | - } | ||
| 830 | - if ((mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online"))) { | ||
| 831 | - logger.info("发现已经在推流"); | ||
| 832 | - sendRtpItem.setStatus(2); | ||
| 833 | - redisCatchStorage.updateSendRTPSever(sendRtpItem); | ||
| 834 | - StringBuffer content = new StringBuffer(200); | ||
| 835 | - content.append("v=0\r\n"); | ||
| 836 | - content.append("o="+ config.getId() +" "+ sdp.getOrigin().getSessionId() +" " + sdp.getOrigin().getSessionVersion() + " IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); | ||
| 837 | - content.append("s=Play\r\n"); | ||
| 838 | - content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); | ||
| 839 | - content.append("t=0 0\r\n"); | ||
| 840 | - if (codecId == null) { | ||
| 841 | - if (mediaTransmissionTCP) { | ||
| 842 | - content.append("m=audio "+ sendRtpItem.getLocalPort()+" TCP/RTP/AVP 8\r\n"); | ||
| 843 | - }else { | ||
| 844 | - content.append("m=audio "+ sendRtpItem.getLocalPort()+" RTP/AVP 8\r\n"); | ||
| 845 | - } | ||
| 846 | - | ||
| 847 | - content.append("a=rtpmap:8 PCMA/8000\r\n"); | ||
| 848 | - }else { | ||
| 849 | - if (codecId == 4) { | ||
| 850 | - if (mediaTransmissionTCP) { | ||
| 851 | - content.append("m=audio "+ sendRtpItem.getLocalPort()+" TCP/RTP/AVP 0\r\n"); | ||
| 852 | - }else { | ||
| 853 | - content.append("m=audio "+ sendRtpItem.getLocalPort()+" RTP/AVP 0\r\n"); | ||
| 854 | - } | ||
| 855 | - content.append("a=rtpmap:0 PCMU/8000\r\n"); | ||
| 856 | - }else { | ||
| 857 | - if (mediaTransmissionTCP) { | ||
| 858 | - content.append("m=audio "+ sendRtpItem.getLocalPort()+" TCP/RTP/AVP 8\r\n"); | ||
| 859 | - }else { | ||
| 860 | - content.append("m=audio "+ sendRtpItem.getLocalPort()+" RTP/AVP 8\r\n"); | ||
| 861 | - } | ||
| 862 | - content.append("a=rtpmap:8 PCMA/8000\r\n"); | ||
| 863 | - } | ||
| 864 | - } | ||
| 865 | - if (sendRtpItem.isTcp()) { | ||
| 866 | - content.append("a=connection:new\r\n"); | ||
| 867 | - if (!sendRtpItem.isTcpActive()) { | ||
| 868 | - content.append("a=setup:active\r\n"); | ||
| 869 | - }else { | ||
| 870 | - content.append("a=setup:passive\r\n"); | ||
| 871 | - } | ||
| 872 | - } | ||
| 873 | - content.append("a=sendonly\r\n"); | ||
| 874 | - content.append("y="+ finalSsrc + "\r\n"); | ||
| 875 | - content.append("f=v/////a/1/8/1\r\n"); | ||
| 876 | - | ||
| 877 | - ParentPlatform parentPlatform = new ParentPlatform(); | ||
| 878 | - parentPlatform.setServerIP(device.getIp()); | ||
| 879 | - parentPlatform.setServerPort(device.getPort()); | ||
| 880 | - parentPlatform.setServerGBId(device.getDeviceId()); | ||
| 881 | - try { | ||
| 882 | - responseSdpAck(evt, content.toString(), parentPlatform); | ||
| 883 | - Dialog dialog = evt.getDialog(); | ||
| 884 | - audioBroadcastCatch.setDialog((SIPDialog) dialog); | ||
| 885 | - audioBroadcastCatch.setRequest((SIPRequest) request); | ||
| 886 | - audioBroadcastManager.update(audioBroadcastCatch); | ||
| 887 | - } catch (SipException e) { | ||
| 888 | - throw new RuntimeException(e); | ||
| 889 | - } catch (InvalidArgumentException e) { | ||
| 890 | - throw new RuntimeException(e); | ||
| 891 | - } catch (ParseException e) { | ||
| 892 | - throw new RuntimeException(e); | ||
| 893 | - } | ||
| 894 | - }else { | ||
| 895 | - // 流不存在时监听流上线 | ||
| 896 | - // 设置等待推流的超时; 默认20s | ||
| 897 | - String waiteStreamTimeoutTaskKey = "waite-stream-" + device.getDeviceId() + audioBroadcastCatch.getChannelId(); | ||
| 898 | - dynamicTask.startDelay(waiteStreamTimeoutTaskKey, ()->{ | ||
| 899 | - logger.info("等待推流超时: {}/{}", app, stream); | ||
| 900 | - subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey); | ||
| 901 | - playService.stopAudioBroadcast(device.getDeviceId(), audioBroadcastCatch.getChannelId()); | ||
| 902 | - // 发送bye | ||
| 903 | - try { | ||
| 904 | - responseAck(evt, Response.BUSY_HERE); | ||
| 905 | - } catch (SipException e) { | ||
| 906 | - throw new RuntimeException(e); | ||
| 907 | - } catch (InvalidArgumentException e) { | ||
| 908 | - throw new RuntimeException(e); | ||
| 909 | - } catch (ParseException e) { | ||
| 910 | - throw new RuntimeException(e); | ||
| 911 | - } | ||
| 912 | - }, 20*1000); | ||
| 913 | - | ||
| 914 | - boolean finalMediaTransmissionTCP = mediaTransmissionTCP; | ||
| 915 | - subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, | ||
| 916 | - (MediaServerItem mediaServerItemInUse, JSONObject json)->{ | ||
| 917 | - logger.info("收到语音对讲推流"); | ||
| 918 | - MediaItem mediaItem = JSON.toJavaObject(json, MediaItem.class); | ||
| 919 | - Integer audioCodecId = null; | ||
| 920 | - if (mediaItem.getTracks() != null && mediaItem.getTracks().size() > 0) { | ||
| 921 | - for (int i = 0; i < mediaItem.getTracks().size(); i++) { | ||
| 922 | - MediaItem.MediaTrack mediaTrack = mediaItem.getTracks().get(i); | ||
| 923 | - if (mediaTrack.getCodecType() == 1) { | ||
| 924 | - audioCodecId = mediaTrack.getCodecId(); | ||
| 925 | - break; | ||
| 926 | - } | ||
| 927 | - } | ||
| 928 | - } | ||
| 929 | - | ||
| 930 | - try { | ||
| 931 | - sendRtpItem.setStatus(2); | ||
| 932 | - redisCatchStorage.updateSendRTPSever(sendRtpItem); | ||
| 933 | - StringBuffer content = new StringBuffer(200); | ||
| 934 | - content.append("v=0\r\n"); | ||
| 935 | - content.append("o="+ config.getId() +" "+ sdp.getOrigin().getSessionId() +" " + sdp.getOrigin().getSessionVersion() + " IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); | ||
| 936 | - content.append("s=Play\r\n"); | ||
| 937 | - content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); | ||
| 938 | - content.append("t=0 0\r\n"); | ||
| 939 | - if (audioCodecId == null) { | ||
| 940 | - if (finalMediaTransmissionTCP) { | ||
| 941 | - content.append("m=audio "+ sendRtpItem.getLocalPort()+" TCP/RTP/AVP 8\r\n"); | ||
| 942 | - }else { | ||
| 943 | - content.append("m=audio "+ sendRtpItem.getLocalPort()+" RTP/AVP 8\r\n"); | ||
| 944 | - } | ||
| 945 | - | ||
| 946 | - content.append("a=rtpmap:8 PCMA/8000\r\n"); | ||
| 947 | - }else { | ||
| 948 | - if (audioCodecId == 4) { | ||
| 949 | - if (finalMediaTransmissionTCP) { | ||
| 950 | - content.append("m=audio "+ sendRtpItem.getLocalPort()+" TCP/RTP/AVP 0\r\n"); | ||
| 951 | - }else { | ||
| 952 | - content.append("m=audio "+ sendRtpItem.getLocalPort()+" RTP/AVP 0\r\n"); | ||
| 953 | - } | ||
| 954 | - content.append("a=rtpmap:0 PCMU/8000\r\n"); | ||
| 955 | - }else { | ||
| 956 | - if (finalMediaTransmissionTCP) { | ||
| 957 | - content.append("m=audio "+ sendRtpItem.getLocalPort()+" TCP/RTP/AVP 8\r\n"); | ||
| 958 | - }else { | ||
| 959 | - content.append("m=audio "+ sendRtpItem.getLocalPort()+" RTP/AVP 8\r\n"); | ||
| 960 | - } | ||
| 961 | - content.append("a=rtpmap:8 PCMA/8000\r\n"); | ||
| 962 | - } | ||
| 963 | - } | ||
| 964 | - content.append("a=sendonly\r\n"); | ||
| 965 | - if (sendRtpItem.isTcp()) { | ||
| 966 | - content.append("a=connection:new\r\n"); | ||
| 967 | - if (!sendRtpItem.isTcpActive()) { | ||
| 968 | - content.append("a=setup:active\r\n"); | ||
| 969 | - }else { | ||
| 970 | - content.append("a=setup:passive\r\n"); | ||
| 971 | - } | ||
| 972 | - } | ||
| 973 | - content.append("y="+ finalSsrc + "\r\n"); | ||
| 974 | - content.append("f=v/////a/1/8/1\r\n"); | ||
| 975 | - | ||
| 976 | - ParentPlatform parentPlatform = new ParentPlatform(); | ||
| 977 | - parentPlatform.setServerIP(device.getIp()); | ||
| 978 | - parentPlatform.setServerPort(device.getPort()); | ||
| 979 | - parentPlatform.setServerGBId(device.getDeviceId()); | ||
| 980 | - | ||
| 981 | - responseSdpAck(evt, content.toString(), parentPlatform); | ||
| 982 | - Dialog dialog = evt.getDialog(); | ||
| 983 | - audioBroadcastCatch.setDialog((SIPDialog) dialog); | ||
| 984 | - audioBroadcastCatch.setRequest((SIPRequest) request); | ||
| 985 | - audioBroadcastManager.update(audioBroadcastCatch); | ||
| 986 | - } catch (SipException e) { | ||
| 987 | - throw new RuntimeException(e); | ||
| 988 | - } catch (InvalidArgumentException e) { | ||
| 989 | - throw new RuntimeException(e); | ||
| 990 | - } catch (ParseException e) { | ||
| 991 | - throw new RuntimeException(e); | ||
| 992 | - } catch (SdpParseException e) { | ||
| 993 | - throw new RuntimeException(e); | ||
| 994 | - } | ||
| 995 | - }); | ||
| 996 | - } | ||
| 997 | - String key = DeferredResultHolder.CALLBACK_CMD_BROADCAST + device.getDeviceId(); | ||
| 998 | - WVPResult<AudioBroadcastResult> wvpResult = new WVPResult<>(); | ||
| 999 | - wvpResult.setCode(0); | ||
| 1000 | - wvpResult.setMsg("success"); | ||
| 1001 | - AudioBroadcastResult audioBroadcastResult = new AudioBroadcastResult(); | ||
| 1002 | - audioBroadcastResult.setApp(app); | ||
| 1003 | - audioBroadcastResult.setStream(stream); | ||
| 1004 | - audioBroadcastResult.setMediaServerItem(new MediaServerItemLite(mediaServerItem)); | ||
| 1005 | - audioBroadcastResult.setCodec("G.711"); | ||
| 1006 | - wvpResult.setData(audioBroadcastResult); | ||
| 1007 | - RequestMessage requestMessage = new RequestMessage(); | ||
| 1008 | - requestMessage.setKey(key); | ||
| 1009 | - requestMessage.setData(wvpResult); | ||
| 1010 | - resultHolder.invokeAllResult(requestMessage); | ||
| 1011 | - } else { | ||
| 1012 | - logger.warn("来自无效设备/平台的请求"); | ||
| 1013 | - responseAck(evt, Response.BAD_REQUEST); | ||
| 1014 | - } | ||
| 1015 | - } | ||
| 1016 | } | 1031 | } |
src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java
| 1 | package com.genersoft.iot.vmp.service; | 1 | package com.genersoft.iot.vmp.service; |
| 2 | 2 | ||
| 3 | import com.alibaba.fastjson.JSONObject; | 3 | import com.alibaba.fastjson.JSONObject; |
| 4 | -import com.genersoft.iot.vmp.gb28181.bean.Device; | ||
| 5 | import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; | 4 | import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; |
| 6 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | 5 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 7 | import com.genersoft.iot.vmp.service.bean.SSRCInfo; | 6 | import com.genersoft.iot.vmp.service.bean.SSRCInfo; |
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
| @@ -6,7 +6,6 @@ import com.alibaba.fastjson.JSONObject; | @@ -6,7 +6,6 @@ import com.alibaba.fastjson.JSONObject; | ||
| 6 | import com.genersoft.iot.vmp.common.VideoManagerConstants; | 6 | import com.genersoft.iot.vmp.common.VideoManagerConstants; |
| 7 | import com.genersoft.iot.vmp.conf.SipConfig; | 7 | import com.genersoft.iot.vmp.conf.SipConfig; |
| 8 | import com.genersoft.iot.vmp.conf.UserSetting; | 8 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 9 | -import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction; | ||
| 10 | import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | 9 | import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
| 11 | import com.genersoft.iot.vmp.gb28181.session.SsrcConfig; | 10 | import com.genersoft.iot.vmp.gb28181.session.SsrcConfig; |
| 12 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | 11 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| @@ -34,11 +33,8 @@ import org.springframework.transaction.TransactionDefinition; | @@ -34,11 +33,8 @@ import org.springframework.transaction.TransactionDefinition; | ||
| 34 | import org.springframework.transaction.TransactionStatus; | 33 | import org.springframework.transaction.TransactionStatus; |
| 35 | import org.springframework.util.StringUtils; | 34 | import org.springframework.util.StringUtils; |
| 36 | 35 | ||
| 37 | -import java.text.ParseException; | ||
| 38 | -import java.text.SimpleDateFormat; | ||
| 39 | import java.time.LocalDateTime; | 36 | import java.time.LocalDateTime; |
| 40 | import java.util.*; | 37 | import java.util.*; |
| 41 | -import java.util.stream.Collectors; | ||
| 42 | 38 | ||
| 43 | /** | 39 | /** |
| 44 | * 媒体服务器节点管理 | 40 | * 媒体服务器节点管理 |
web_src/package-lock.json
| @@ -50,7 +50,7 @@ | @@ -50,7 +50,7 @@ | ||
| 50 | "postcss-url": "^7.2.1", | 50 | "postcss-url": "^7.2.1", |
| 51 | "rimraf": "^2.6.0", | 51 | "rimraf": "^2.6.0", |
| 52 | "semver": "^5.3.0", | 52 | "semver": "^5.3.0", |
| 53 | - "shelljs": "^0.7.6", | 53 | + "shelljs": "^0.8.5", |
| 54 | "uglifyjs-webpack-plugin": "^1.1.1", | 54 | "uglifyjs-webpack-plugin": "^1.1.1", |
| 55 | "url-loader": "^0.5.8", | 55 | "url-loader": "^0.5.8", |
| 56 | "vue-loader": "^13.3.0", | 56 | "vue-loader": "^13.3.0", |
| @@ -11655,9 +11655,9 @@ | @@ -11655,9 +11655,9 @@ | ||
| 11655 | } | 11655 | } |
| 11656 | }, | 11656 | }, |
| 11657 | "node_modules/shelljs": { | 11657 | "node_modules/shelljs": { |
| 11658 | - "version": "0.7.8", | ||
| 11659 | - "resolved": "https://registry.npm.taobao.org/shelljs/download/shelljs-0.7.8.tgz", | ||
| 11660 | - "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", | 11658 | + "version": "0.8.5", |
| 11659 | + "resolved": "https://registry.npmmirror.com/shelljs/-/shelljs-0.8.5.tgz", | ||
| 11660 | + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", | ||
| 11661 | "dev": true, | 11661 | "dev": true, |
| 11662 | "dependencies": { | 11662 | "dependencies": { |
| 11663 | "glob": "^7.0.0", | 11663 | "glob": "^7.0.0", |
| @@ -11668,8 +11668,7 @@ | @@ -11668,8 +11668,7 @@ | ||
| 11668 | "shjs": "bin/shjs" | 11668 | "shjs": "bin/shjs" |
| 11669 | }, | 11669 | }, |
| 11670 | "engines": { | 11670 | "engines": { |
| 11671 | - "iojs": "*", | ||
| 11672 | - "node": ">=0.11.0" | 11671 | + "node": ">=4" |
| 11673 | } | 11672 | } |
| 11674 | }, | 11673 | }, |
| 11675 | "node_modules/shellwords": { | 11674 | "node_modules/shellwords": { |
| @@ -24156,9 +24155,9 @@ | @@ -24156,9 +24155,9 @@ | ||
| 24156 | "dev": true | 24155 | "dev": true |
| 24157 | }, | 24156 | }, |
| 24158 | "shelljs": { | 24157 | "shelljs": { |
| 24159 | - "version": "0.7.8", | ||
| 24160 | - "resolved": "https://registry.npm.taobao.org/shelljs/download/shelljs-0.7.8.tgz", | ||
| 24161 | - "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", | 24158 | + "version": "0.8.5", |
| 24159 | + "resolved": "https://registry.npmmirror.com/shelljs/-/shelljs-0.8.5.tgz", | ||
| 24160 | + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", | ||
| 24162 | "dev": true, | 24161 | "dev": true, |
| 24163 | "requires": { | 24162 | "requires": { |
| 24164 | "glob": "^7.0.0", | 24163 | "glob": "^7.0.0", |