Commit 663130df4556c35b8b390a74df571af8185d974d
1 parent
a209d173
完善支持语音对讲talk
Showing
26 changed files
with
458 additions
and
342 deletions
src/main/java/com/genersoft/iot/vmp/gb28181/bean/AudioBroadcastCatch.java
| 1 | package com.genersoft.iot.vmp.gb28181.bean; | 1 | package com.genersoft.iot.vmp.gb28181.bean; |
| 2 | 2 | ||
| 3 | 3 | ||
| 4 | +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | ||
| 4 | import gov.nist.javax.sip.message.SIPResponse; | 5 | import gov.nist.javax.sip.message.SIPResponse; |
| 5 | 6 | ||
| 6 | /** | 7 | /** |
| @@ -10,10 +11,11 @@ import gov.nist.javax.sip.message.SIPResponse; | @@ -10,10 +11,11 @@ import gov.nist.javax.sip.message.SIPResponse; | ||
| 10 | public class AudioBroadcastCatch { | 11 | public class AudioBroadcastCatch { |
| 11 | 12 | ||
| 12 | 13 | ||
| 13 | - public AudioBroadcastCatch(String deviceId, String channelId, AudioBroadcastCatchStatus status) { | 14 | + public AudioBroadcastCatch(String deviceId, String channelId, AudioBroadcastCatchStatus status, MediaServerItem mediaServerItem) { |
| 14 | this.deviceId = deviceId; | 15 | this.deviceId = deviceId; |
| 15 | this.channelId = channelId; | 16 | this.channelId = channelId; |
| 16 | this.status = status; | 17 | this.status = status; |
| 18 | + this.mediaServerItem = mediaServerItem; | ||
| 17 | } | 19 | } |
| 18 | 20 | ||
| 19 | public AudioBroadcastCatch() { | 21 | public AudioBroadcastCatch() { |
| @@ -39,6 +41,8 @@ public class AudioBroadcastCatch { | @@ -39,6 +41,8 @@ public class AudioBroadcastCatch { | ||
| 39 | */ | 41 | */ |
| 40 | private SipTransactionInfo sipTransactionInfo; | 42 | private SipTransactionInfo sipTransactionInfo; |
| 41 | 43 | ||
| 44 | + private MediaServerItem mediaServerItem; | ||
| 45 | + | ||
| 42 | 46 | ||
| 43 | public String getDeviceId() { | 47 | public String getDeviceId() { |
| 44 | return deviceId; | 48 | return deviceId; |
| @@ -75,4 +79,12 @@ public class AudioBroadcastCatch { | @@ -75,4 +79,12 @@ public class AudioBroadcastCatch { | ||
| 75 | public void setSipTransactionInfoByRequset(SIPResponse response) { | 79 | public void setSipTransactionInfoByRequset(SIPResponse response) { |
| 76 | this.sipTransactionInfo = new SipTransactionInfo(response, false); | 80 | this.sipTransactionInfo = new SipTransactionInfo(response, false); |
| 77 | } | 81 | } |
| 82 | + | ||
| 83 | + public MediaServerItem getMediaServerItem() { | ||
| 84 | + return mediaServerItem; | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + public void setMediaServerItem(MediaServerItem mediaServerItem) { | ||
| 88 | + this.mediaServerItem = mediaServerItem; | ||
| 89 | + } | ||
| 78 | } | 90 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java
| @@ -49,7 +49,7 @@ public class SendRtpItem { | @@ -49,7 +49,7 @@ public class SendRtpItem { | ||
| 49 | /** | 49 | /** |
| 50 | * 设备推流的streamId | 50 | * 设备推流的streamId |
| 51 | */ | 51 | */ |
| 52 | - private String streamId; | 52 | + private String stream; |
| 53 | 53 | ||
| 54 | /** | 54 | /** |
| 55 | * 是否为tcp | 55 | * 是否为tcp |
| @@ -117,6 +117,11 @@ public class SendRtpItem { | @@ -117,6 +117,11 @@ public class SendRtpItem { | ||
| 117 | */ | 117 | */ |
| 118 | private InviteStreamType playType; | 118 | private InviteStreamType playType; |
| 119 | 119 | ||
| 120 | + /** | ||
| 121 | + * 发流的同时收流 | ||
| 122 | + */ | ||
| 123 | + private String receiveStream; | ||
| 124 | + | ||
| 120 | public String getIp() { | 125 | public String getIp() { |
| 121 | return ip; | 126 | return ip; |
| 122 | } | 127 | } |
| @@ -181,12 +186,12 @@ public class SendRtpItem { | @@ -181,12 +186,12 @@ public class SendRtpItem { | ||
| 181 | this.app = app; | 186 | this.app = app; |
| 182 | } | 187 | } |
| 183 | 188 | ||
| 184 | - public String getStreamId() { | ||
| 185 | - return streamId; | 189 | + public String getStream() { |
| 190 | + return stream; | ||
| 186 | } | 191 | } |
| 187 | 192 | ||
| 188 | - public void setStreamId(String streamId) { | ||
| 189 | - this.streamId = streamId; | 193 | + public void setStream(String stream) { |
| 194 | + this.stream = stream; | ||
| 190 | } | 195 | } |
| 191 | 196 | ||
| 192 | public boolean isTcp() { | 197 | public boolean isTcp() { |
| @@ -292,4 +297,12 @@ public class SendRtpItem { | @@ -292,4 +297,12 @@ public class SendRtpItem { | ||
| 292 | public void setRtcp(boolean rtcp) { | 297 | public void setRtcp(boolean rtcp) { |
| 293 | this.rtcp = rtcp; | 298 | this.rtcp = rtcp; |
| 294 | } | 299 | } |
| 300 | + | ||
| 301 | + public String getReceiveStream() { | ||
| 302 | + return receiveStream; | ||
| 303 | + } | ||
| 304 | + | ||
| 305 | + public void setReceiveStream(String receiveStream) { | ||
| 306 | + this.receiveStream = receiveStream; | ||
| 307 | + } | ||
| 295 | } | 308 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java
| 1 | package com.genersoft.iot.vmp.gb28181.event; | 1 | package com.genersoft.iot.vmp.gb28181.event; |
| 2 | 2 | ||
| 3 | -import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | ||
| 4 | import com.genersoft.iot.vmp.gb28181.bean.DeviceNotFoundEvent; | 3 | import com.genersoft.iot.vmp.gb28181.bean.DeviceNotFoundEvent; |
| 5 | import gov.nist.javax.sip.message.SIPRequest; | 4 | import gov.nist.javax.sip.message.SIPRequest; |
| 6 | import org.slf4j.Logger; | 5 | import org.slf4j.Logger; |
src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java
src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java
| @@ -74,12 +74,12 @@ public class SipRunner implements CommandLineRunner { | @@ -74,12 +74,12 @@ public class SipRunner implements CommandLineRunner { | ||
| 74 | if (sendRtpItems.size() > 0) { | 74 | if (sendRtpItems.size() > 0) { |
| 75 | for (SendRtpItem sendRtpItem : sendRtpItems) { | 75 | for (SendRtpItem sendRtpItem : sendRtpItems) { |
| 76 | MediaServerItem mediaServerItem = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | 76 | MediaServerItem mediaServerItem = mediaServerService.getOne(sendRtpItem.getMediaServerId()); |
| 77 | - redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(),sendRtpItem.getChannelId(), sendRtpItem.getCallId(),sendRtpItem.getStreamId()); | 77 | + redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(),sendRtpItem.getChannelId(), sendRtpItem.getCallId(),sendRtpItem.getStream()); |
| 78 | if (mediaServerItem != null) { | 78 | if (mediaServerItem != null) { |
| 79 | Map<String, Object> param = new HashMap<>(); | 79 | Map<String, Object> param = new HashMap<>(); |
| 80 | param.put("vhost","__defaultVhost__"); | 80 | param.put("vhost","__defaultVhost__"); |
| 81 | param.put("app",sendRtpItem.getApp()); | 81 | param.put("app",sendRtpItem.getApp()); |
| 82 | - param.put("stream",sendRtpItem.getStreamId()); | 82 | + param.put("stream",sendRtpItem.getStream()); |
| 83 | param.put("ssrc",sendRtpItem.getSsrc()); | 83 | param.put("ssrc",sendRtpItem.getSsrc()); |
| 84 | JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(mediaServerItem, param); | 84 | JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(mediaServerItem, param); |
| 85 | if (jsonObject != null && jsonObject.getInteger("code") == 0) { | 85 | if (jsonObject != null && jsonObject.getInteger("code") == 0) { |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
| @@ -2,10 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd; | @@ -2,10 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd; | ||
| 2 | 2 | ||
| 3 | import com.genersoft.iot.vmp.common.StreamInfo; | 3 | import com.genersoft.iot.vmp.common.StreamInfo; |
| 4 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | 4 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; |
| 5 | -import com.genersoft.iot.vmp.gb28181.bean.Device; | ||
| 6 | -import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; | ||
| 7 | -import com.genersoft.iot.vmp.gb28181.bean.InviteStreamCallback; | ||
| 8 | -import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo; | 5 | +import com.genersoft.iot.vmp.gb28181.bean.*; |
| 9 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | 6 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| 10 | import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; | 7 | import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; |
| 11 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | 8 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| @@ -131,7 +128,7 @@ public interface ISIPCommander { | @@ -131,7 +128,7 @@ public interface ISIPCommander { | ||
| 131 | */ | 128 | */ |
| 132 | void streamByeCmd(Device device, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException; | 129 | void streamByeCmd(Device device, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException; |
| 133 | 130 | ||
| 134 | - void talkStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, String callId, ZlmHttpHookSubscribe.Event event, ZlmHttpHookSubscribe.Event eventForPush, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; | 131 | + void talkStreamCmd(MediaServerItem mediaServerItem, SendRtpItem sendRtpItem, Device device, String channelId, String callId, ZlmHttpHookSubscribe.Event event, ZlmHttpHookSubscribe.Event eventForPush, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; |
| 135 | 132 | ||
| 136 | 133 | ||
| 137 | void streamByeCmd(Device device, String channelId, String stream, String callId) throws InvalidArgumentException, ParseException, SipException, SsrcTransactionNotFoundException; | 134 | void streamByeCmd(Device device, String channelId, String stream, String callId) throws InvalidArgumentException, ParseException, SipException, SsrcTransactionNotFoundException; |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
| @@ -32,7 +32,6 @@ import org.springframework.beans.factory.annotation.Autowired; | @@ -32,7 +32,6 @@ import org.springframework.beans.factory.annotation.Autowired; | ||
| 32 | import org.springframework.context.annotation.DependsOn; | 32 | import org.springframework.context.annotation.DependsOn; |
| 33 | import org.springframework.stereotype.Component; | 33 | import org.springframework.stereotype.Component; |
| 34 | import org.springframework.util.ObjectUtils; | 34 | import org.springframework.util.ObjectUtils; |
| 35 | -import org.springframework.util.StringUtils; | ||
| 36 | 35 | ||
| 37 | import javax.sip.InvalidArgumentException; | 36 | import javax.sip.InvalidArgumentException; |
| 38 | import javax.sip.ResponseEvent; | 37 | import javax.sip.ResponseEvent; |
| @@ -584,9 +583,9 @@ public class SIPCommander implements ISIPCommander { | @@ -584,9 +583,9 @@ public class SIPCommander implements ISIPCommander { | ||
| 584 | } | 583 | } |
| 585 | 584 | ||
| 586 | @Override | 585 | @Override |
| 587 | - public void talkStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, String callId, ZlmHttpHookSubscribe.Event event, ZlmHttpHookSubscribe.Event eventForPush, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | 586 | + public void talkStreamCmd(MediaServerItem mediaServerItem, SendRtpItem sendRtpItem, Device device, String channelId, String callId, ZlmHttpHookSubscribe.Event event, ZlmHttpHookSubscribe.Event eventForPush, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { |
| 588 | 587 | ||
| 589 | - String stream = ssrcInfo.getStream(); | 588 | + String stream = sendRtpItem.getStream(); |
| 590 | 589 | ||
| 591 | if (device == null) { | 590 | if (device == null) { |
| 592 | return; | 591 | return; |
| @@ -597,7 +596,7 @@ public class SIPCommander implements ISIPCommander { | @@ -597,7 +596,7 @@ public class SIPCommander implements ISIPCommander { | ||
| 597 | return; | 596 | return; |
| 598 | } | 597 | } |
| 599 | 598 | ||
| 600 | - logger.info("[语音对讲] {} 分配的ZLM为: {} [{}:{}]", stream, mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort()); | 599 | + logger.info("[语音对讲] {} 分配的ZLM为: {} [{}:{}]", stream, mediaServerItem.getId(), mediaServerItem.getIp(), sendRtpItem.getPort()); |
| 601 | HookSubscribeForStreamChange hookSubscribeForStreamChange = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId()); | 600 | HookSubscribeForStreamChange hookSubscribeForStreamChange = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId()); |
| 602 | subscribe.addSubscribe(hookSubscribeForStreamChange, (MediaServerItem mediaServerItemInUse, JSONObject json) -> { | 601 | subscribe.addSubscribe(hookSubscribeForStreamChange, (MediaServerItem mediaServerItemInUse, JSONObject json) -> { |
| 603 | if (event != null) { | 602 | if (event != null) { |
| @@ -622,24 +621,27 @@ public class SIPCommander implements ISIPCommander { | @@ -622,24 +621,27 @@ public class SIPCommander implements ISIPCommander { | ||
| 622 | content.append("c=IN IP4 " + mediaServerItem.getSdpIp() + "\r\n"); | 621 | content.append("c=IN IP4 " + mediaServerItem.getSdpIp() + "\r\n"); |
| 623 | content.append("t=0 0\r\n"); | 622 | content.append("t=0 0\r\n"); |
| 624 | 623 | ||
| 625 | - content.append("m=audio " + ssrcInfo.getPort() + " RTP/AVP 8\r\n"); | 624 | + content.append("m=audio " + sendRtpItem.getPort() + " TCP/RTP/AVP 8\r\n"); |
| 625 | + content.append("a=setup:passive\r\n"); | ||
| 626 | + content.append("a=connection:new\r\n"); | ||
| 626 | content.append("a=sendrecv\r\n"); | 627 | content.append("a=sendrecv\r\n"); |
| 627 | content.append("a=rtpmap:8 PCMA/8000\r\n"); | 628 | content.append("a=rtpmap:8 PCMA/8000\r\n"); |
| 628 | 629 | ||
| 629 | - content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc | 630 | + content.append("y=" + sendRtpItem.getSsrc() + "\r\n");//ssrc |
| 630 | // f字段:f= v/编码格式/分辨率/帧率/码率类型/码率大小a/编码格式/码率大小/采样率 | 631 | // f字段:f= v/编码格式/分辨率/帧率/码率类型/码率大小a/编码格式/码率大小/采样率 |
| 631 | content.append("f=v/////a/1/8/1" + "\r\n"); | 632 | content.append("f=v/////a/1/8/1" + "\r\n"); |
| 632 | 633 | ||
| 633 | - Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(), callIdHeader); | 634 | + Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), |
| 635 | + SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, sendRtpItem.getSsrc(), callIdHeader); | ||
| 634 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> { | 636 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> { |
| 635 | - streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); | ||
| 636 | - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | 637 | + streamSession.remove(device.getDeviceId(), channelId, sendRtpItem.getStream()); |
| 638 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc()); | ||
| 637 | errorEvent.response(e); | 639 | errorEvent.response(e); |
| 638 | }), e -> { | 640 | }), e -> { |
| 639 | // 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值 | 641 | // 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值 |
| 640 | ResponseEvent responseEvent = (ResponseEvent) e.event; | 642 | ResponseEvent responseEvent = (ResponseEvent) e.event; |
| 641 | SIPResponse response = (SIPResponse) responseEvent.getResponse(); | 643 | SIPResponse response = (SIPResponse) responseEvent.getResponse(); |
| 642 | - streamSession.put(device.getDeviceId(), channelId, "talk", stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.play); | 644 | + streamSession.put(device.getDeviceId(), channelId, "talk", stream, sendRtpItem.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.play); |
| 643 | okEvent.response(e); | 645 | okEvent.response(e); |
| 644 | }); | 646 | }); |
| 645 | } | 647 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
| @@ -675,7 +675,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { | @@ -675,7 +675,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { | ||
| 675 | MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); | 675 | MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); |
| 676 | if (mediaServerItem != null) { | 676 | if (mediaServerItem != null) { |
| 677 | mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc()); | 677 | mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc()); |
| 678 | - zlmrtpServerFactory.closeRtpServer(mediaServerItem, sendRtpItem.getStreamId()); | 678 | + zlmrtpServerFactory.closeRtpServer(mediaServerItem, sendRtpItem.getStream()); |
| 679 | } | 679 | } |
| 680 | SIPRequest byeRequest = headerProviderPlatformProvider.createByeRequest(platform, sendRtpItem); | 680 | SIPRequest byeRequest = headerProviderPlatformProvider.createByeRequest(platform, sendRtpItem); |
| 681 | if (byeRequest == null) { | 681 | if (byeRequest == null) { |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
| @@ -102,12 +102,12 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In | @@ -102,12 +102,12 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In | ||
| 102 | } | 102 | } |
| 103 | String isUdp = sendRtpItem.isTcp() ? "0" : "1"; | 103 | String isUdp = sendRtpItem.isTcp() ? "0" : "1"; |
| 104 | MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | 104 | MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); |
| 105 | - logger.info("收到ACK,rtp/{}开始向上级推流, 目标={}:{},SSRC={}, RTCP={}", sendRtpItem.getStreamId(), | 105 | + logger.info("收到ACK,rtp/{}开始向上级推流, 目标={}:{},SSRC={}, RTCP={}", sendRtpItem.getStream(), |
| 106 | sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isRtcp()); | 106 | sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isRtcp()); |
| 107 | Map<String, Object> param = new HashMap<>(12); | 107 | Map<String, Object> param = new HashMap<>(12); |
| 108 | param.put("vhost","__defaultVhost__"); | 108 | param.put("vhost","__defaultVhost__"); |
| 109 | param.put("app",sendRtpItem.getApp()); | 109 | param.put("app",sendRtpItem.getApp()); |
| 110 | - param.put("stream",sendRtpItem.getStreamId()); | 110 | + param.put("stream",sendRtpItem.getStream()); |
| 111 | param.put("ssrc", sendRtpItem.getSsrc()); | 111 | param.put("ssrc", sendRtpItem.getSsrc()); |
| 112 | param.put("src_port", sendRtpItem.getLocalPort()); | 112 | param.put("src_port", sendRtpItem.getLocalPort()); |
| 113 | param.put("pt", sendRtpItem.getPt()); | 113 | param.put("pt", sendRtpItem.getPt()); |
| @@ -121,7 +121,7 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In | @@ -121,7 +121,7 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In | ||
| 121 | 121 | ||
| 122 | if (mediaInfo == null) { | 122 | if (mediaInfo == null) { |
| 123 | RequestPushStreamMsg requestPushStreamMsg = RequestPushStreamMsg.getInstance( | 123 | RequestPushStreamMsg requestPushStreamMsg = RequestPushStreamMsg.getInstance( |
| 124 | - sendRtpItem.getMediaServerId(), sendRtpItem.getApp(), sendRtpItem.getStreamId(), | 124 | + sendRtpItem.getMediaServerId(), sendRtpItem.getApp(), sendRtpItem.getStream(), |
| 125 | sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isTcp(), | 125 | sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isTcp(), |
| 126 | sendRtpItem.getLocalPort(), sendRtpItem.getPt(), sendRtpItem.isUsePs(), sendRtpItem.isOnlyAudio()); | 126 | sendRtpItem.getLocalPort(), sendRtpItem.getPt(), sendRtpItem.isUsePs(), sendRtpItem.isOnlyAudio()); |
| 127 | redisGbPlayMsgListener.sendMsgForStartSendRtpStream(sendRtpItem.getServerId(), requestPushStreamMsg, json -> { | 127 | redisGbPlayMsgListener.sendMsgForStartSendRtpStream(sendRtpItem.getServerId(), requestPushStreamMsg, json -> { |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
| @@ -97,7 +97,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | @@ -97,7 +97,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | ||
| 97 | 97 | ||
| 98 | if (sendRtpItem != null){ | 98 | if (sendRtpItem != null){ |
| 99 | logger.info("[收到bye] {}/{}", sendRtpItem.getPlatformId(), sendRtpItem.getChannelId()); | 99 | logger.info("[收到bye] {}/{}", sendRtpItem.getPlatformId(), sendRtpItem.getChannelId()); |
| 100 | - String streamId = sendRtpItem.getStreamId(); | 100 | + String streamId = sendRtpItem.getStream(); |
| 101 | MediaServerItem mediaServerItem = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | 101 | MediaServerItem mediaServerItem = mediaServerService.getOne(sendRtpItem.getMediaServerId()); |
| 102 | if (mediaServerItem == null) { | 102 | if (mediaServerItem == null) { |
| 103 | return; | 103 | return; |
| @@ -105,7 +105,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | @@ -105,7 +105,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | ||
| 105 | 105 | ||
| 106 | Boolean ready = zlmrtpServerFactory.isStreamReady(mediaServerItem, sendRtpItem.getApp(), streamId); | 106 | Boolean ready = zlmrtpServerFactory.isStreamReady(mediaServerItem, sendRtpItem.getApp(), streamId); |
| 107 | if (!ready) { | 107 | if (!ready) { |
| 108 | - logger.info("[收到bye] 发现流{}/{}已经结束,不需处理", sendRtpItem.getApp(), sendRtpItem.getStreamId()); | 108 | + logger.info("[收到bye] 发现流{}/{}已经结束,不需处理", sendRtpItem.getApp(), sendRtpItem.getStream()); |
| 109 | return; | 109 | return; |
| 110 | } | 110 | } |
| 111 | Map<String, Object> param = new HashMap<>(); | 111 | Map<String, Object> param = new HashMap<>(); |
| @@ -113,7 +113,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | @@ -113,7 +113,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | ||
| 113 | param.put("app",sendRtpItem.getApp()); | 113 | param.put("app",sendRtpItem.getApp()); |
| 114 | param.put("stream",streamId); | 114 | param.put("stream",streamId); |
| 115 | param.put("ssrc",sendRtpItem.getSsrc()); | 115 | param.put("ssrc",sendRtpItem.getSsrc()); |
| 116 | - logger.info("[收到bye] 停止向上级推流:{}", streamId); | 116 | + logger.info("[收到bye] 停止推流:{}", streamId); |
| 117 | MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | 117 | MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); |
| 118 | redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(), callIdHeader.getCallId(), null); | 118 | redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(), callIdHeader.getCallId(), null); |
| 119 | zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param); | 119 | zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param); |
| @@ -129,15 +129,14 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | @@ -129,15 +129,14 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | ||
| 129 | try { | 129 | try { |
| 130 | logger.warn("[停止点播] {}/{}", sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); | 130 | logger.warn("[停止点播] {}/{}", sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); |
| 131 | cmder.streamByeCmd(device, sendRtpItem.getChannelId(), streamId, null); | 131 | cmder.streamByeCmd(device, sendRtpItem.getChannelId(), streamId, null); |
| 132 | - } catch (InvalidArgumentException | ParseException | SipException | | ||
| 133 | - SsrcTransactionNotFoundException e) { | 132 | + } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) { |
| 134 | logger.error("[收到bye] {} 无其它观看者,通知设备停止推流, 发送BYE失败 {}",streamId, e.getMessage()); | 133 | logger.error("[收到bye] {} 无其它观看者,通知设备停止推流, 发送BYE失败 {}",streamId, e.getMessage()); |
| 135 | } | 134 | } |
| 136 | } | 135 | } |
| 137 | 136 | ||
| 138 | if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) { | 137 | if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) { |
| 139 | MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, | 138 | MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, |
| 140 | - sendRtpItem.getApp(), sendRtpItem.getStreamId(), sendRtpItem.getChannelId(), | 139 | + sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getChannelId(), |
| 141 | sendRtpItem.getPlatformId(), null, null, sendRtpItem.getMediaServerId()); | 140 | sendRtpItem.getPlatformId(), null, null, sendRtpItem.getMediaServerId()); |
| 142 | redisCatchStorage.sendStreamPushRequestedMsg(messageForPushChannel); | 141 | redisCatchStorage.sendStreamPushRequestedMsg(messageForPushChannel); |
| 143 | } | 142 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
| @@ -478,7 +478,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -478,7 +478,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 478 | if ("Playback".equalsIgnoreCase(sessionName)) { | 478 | if ("Playback".equalsIgnoreCase(sessionName)) { |
| 479 | sendRtpItem.setPlayType(InviteStreamType.PLAYBACK); | 479 | sendRtpItem.setPlayType(InviteStreamType.PLAYBACK); |
| 480 | SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, device.isSsrcCheck(), true); | 480 | SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, device.isSsrcCheck(), true); |
| 481 | - sendRtpItem.setStreamId(ssrcInfo.getStream()); | 481 | + sendRtpItem.setStream(ssrcInfo.getStream()); |
| 482 | // 写入redis, 超时时回复 | 482 | // 写入redis, 超时时回复 |
| 483 | redisCatchStorage.updateSendRTPSever(sendRtpItem); | 483 | redisCatchStorage.updateSendRTPSever(sendRtpItem); |
| 484 | playService.playBack(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, DateUtil.formatter.format(start), | 484 | playService.playBack(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, DateUtil.formatter.format(start), |
| @@ -523,7 +523,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -523,7 +523,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 523 | } | 523 | } |
| 524 | SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, device.isSsrcCheck(), false); | 524 | SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, device.isSsrcCheck(), false); |
| 525 | logger.info(JSONObject.toJSONString(ssrcInfo)); | 525 | logger.info(JSONObject.toJSONString(ssrcInfo)); |
| 526 | - sendRtpItem.setStreamId(ssrcInfo.getStream()); | 526 | + sendRtpItem.setStream(ssrcInfo.getStream()); |
| 527 | sendRtpItem.setSsrc(ssrc.equals(ssrcDefault) ? ssrcInfo.getSsrc() : ssrc); | 527 | sendRtpItem.setSsrc(ssrc.equals(ssrcDefault) ? ssrcInfo.getSsrc() : ssrc); |
| 528 | 528 | ||
| 529 | // 写入redis, 超时时回复 | 529 | // 写入redis, 超时时回复 |
| @@ -533,12 +533,12 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -533,12 +533,12 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 533 | redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), finalChannelId, callIdHeader.getCallId(), null); | 533 | redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), finalChannelId, callIdHeader.getCallId(), null); |
| 534 | }); | 534 | }); |
| 535 | } else { | 535 | } else { |
| 536 | - sendRtpItem.setStreamId(playTransaction.getStream()); | 536 | + sendRtpItem.setStream(playTransaction.getStream()); |
| 537 | // 写入redis, 超时时回复 | 537 | // 写入redis, 超时时回复 |
| 538 | redisCatchStorage.updateSendRTPSever(sendRtpItem); | 538 | redisCatchStorage.updateSendRTPSever(sendRtpItem); |
| 539 | JSONObject jsonObject = new JSONObject(); | 539 | JSONObject jsonObject = new JSONObject(); |
| 540 | jsonObject.put("app", sendRtpItem.getApp()); | 540 | jsonObject.put("app", sendRtpItem.getApp()); |
| 541 | - jsonObject.put("stream", sendRtpItem.getStreamId()); | 541 | + jsonObject.put("stream", sendRtpItem.getStream()); |
| 542 | hookEvent.response(mediaServerItem, jsonObject); | 542 | hookEvent.response(mediaServerItem, jsonObject); |
| 543 | } | 543 | } |
| 544 | } | 544 | } |
| @@ -986,9 +986,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -986,9 +986,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 986 | logger.info("设备{}请求语音流,地址:{}:{},ssrc:{}, {}", requesterId, addressStr, port, ssrc, | 986 | logger.info("设备{}请求语音流,地址:{}:{},ssrc:{}, {}", requesterId, addressStr, port, ssrc, |
| 987 | mediaTransmissionTCP ? (tcpActive? "TCP主动":"TCP被动") : "UDP"); | 987 | mediaTransmissionTCP ? (tcpActive? "TCP主动":"TCP被动") : "UDP"); |
| 988 | 988 | ||
| 989 | - MediaServerItem mediaServerItem = playService.getNewMediaServerItem(device); | 989 | + MediaServerItem mediaServerItem = audioBroadcastCatch.getMediaServerItem(); |
| 990 | if (mediaServerItem == null) { | 990 | if (mediaServerItem == null) { |
| 991 | - logger.warn("未找到可用的zlm"); | 991 | + logger.warn("未找到语音喊话使用的zlm"); |
| 992 | try { | 992 | try { |
| 993 | responseAck(request, Response.BUSY_HERE); | 993 | responseAck(request, Response.BUSY_HERE); |
| 994 | } catch (SipException | InvalidArgumentException | ParseException e) { | 994 | } catch (SipException | InvalidArgumentException | ParseException e) { |
| @@ -1022,7 +1022,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -1022,7 +1022,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 1022 | sendRtpItem.setPlatformId(requesterId); | 1022 | sendRtpItem.setPlatformId(requesterId); |
| 1023 | sendRtpItem.setStatus(1); | 1023 | sendRtpItem.setStatus(1); |
| 1024 | sendRtpItem.setApp(app); | 1024 | sendRtpItem.setApp(app); |
| 1025 | - sendRtpItem.setStreamId(stream); | 1025 | + sendRtpItem.setStream(stream); |
| 1026 | sendRtpItem.setPt(8); | 1026 | sendRtpItem.setPt(8); |
| 1027 | sendRtpItem.setUsePs(false); | 1027 | sendRtpItem.setUsePs(false); |
| 1028 | sendRtpItem.setRtcp(false); | 1028 | sendRtpItem.setRtcp(false); |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/info/InfoRequestProcessor.java
| @@ -102,7 +102,7 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I | @@ -102,7 +102,7 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I | ||
| 102 | String contentSubType = header.getContentSubType(); | 102 | String contentSubType = header.getContentSubType(); |
| 103 | if ("Application".equalsIgnoreCase(contentType) && "MANSRTSP".equalsIgnoreCase(contentSubType)) { | 103 | if ("Application".equalsIgnoreCase(contentType) && "MANSRTSP".equalsIgnoreCase(contentSubType)) { |
| 104 | SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, null, callIdHeader.getCallId()); | 104 | SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, null, callIdHeader.getCallId()); |
| 105 | - String streamId = sendRtpItem.getStreamId(); | 105 | + String streamId = sendRtpItem.getStream(); |
| 106 | StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null); | 106 | StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null); |
| 107 | if (null == streamInfo) { | 107 | if (null == streamInfo) { |
| 108 | responseAck(request, Response.NOT_FOUND, "stream " + streamId + " not found"); | 108 | responseAck(request, Response.NOT_FOUND, "stream " + streamId + " not found"); |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java
| @@ -90,7 +90,7 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i | @@ -90,7 +90,7 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i | ||
| 90 | 90 | ||
| 91 | try { | 91 | try { |
| 92 | cmder.streamByeCmd(device, ssrcTransaction.getChannelId(), null, callIdHeader.getCallId()); | 92 | cmder.streamByeCmd(device, ssrcTransaction.getChannelId(), null, callIdHeader.getCallId()); |
| 93 | - } catch (InvalidArgumentException | ParseException | SsrcTransactionNotFoundException | SipException e) { | 93 | + } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) { |
| 94 | logger.error("[录像流]推送完毕,收到关流通知, 发送BYE失败 {}", e.getMessage()); | 94 | logger.error("[录像流]推送完毕,收到关流通知, 发送BYE失败 {}", e.getMessage()); |
| 95 | } | 95 | } |
| 96 | 96 |
src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java
| @@ -122,7 +122,7 @@ public class SipUtils { | @@ -122,7 +122,7 @@ public class SipUtils { | ||
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | public static String getNewCallId() { | 124 | public static String getNewCallId() { |
| 125 | - return (int) Math.floor(Math.random() * 10000) + ""; | 125 | + return (int) Math.floor(Math.random() * 1000000000) + ""; |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | public static int getTypeCodeFromGbCode(String deviceId) { | 128 | public static int getTypeCodeFromGbCode(String deviceId) { |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
| @@ -9,9 +9,9 @@ import com.genersoft.iot.vmp.gb28181.bean.*; | @@ -9,9 +9,9 @@ import com.genersoft.iot.vmp.gb28181.bean.*; | ||
| 9 | import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | 9 | import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
| 10 | import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; | 10 | import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; |
| 11 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | 11 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 12 | -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; | ||
| 13 | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; | 12 | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
| 14 | import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | 13 | import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; |
| 14 | +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; | ||
| 15 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | 15 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; |
| 16 | import com.genersoft.iot.vmp.media.zlm.dto.HookType; | 16 | import com.genersoft.iot.vmp.media.zlm.dto.HookType; |
| 17 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | 17 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| @@ -274,12 +274,12 @@ public class ZLMHttpHookListener { | @@ -274,12 +274,12 @@ public class ZLMHttpHookListener { | ||
| 274 | logger.info("[ZLM HOOK] 流注销, {}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); | 274 | logger.info("[ZLM HOOK] 流注销, {}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); |
| 275 | } | 275 | } |
| 276 | 276 | ||
| 277 | - | 277 | + MediaServerItem mediaInfo = mediaServerService.getOne(param.getMediaServerId()); |
| 278 | JSONObject json = (JSONObject) JSON.toJSON(param); | 278 | JSONObject json = (JSONObject) JSON.toJSON(param); |
| 279 | taskExecutor.execute(() -> { | 279 | taskExecutor.execute(() -> { |
| 280 | ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_stream_changed, json); | 280 | ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_stream_changed, json); |
| 281 | if (subscribe != null) { | 281 | if (subscribe != null) { |
| 282 | - MediaServerItem mediaInfo = mediaServerService.getOne(param.getMediaServerId()); | 282 | + |
| 283 | if (mediaInfo != null) { | 283 | if (mediaInfo != null) { |
| 284 | subscribe.response(mediaInfo, json); | 284 | subscribe.response(mediaInfo, json); |
| 285 | } | 285 | } |
| @@ -343,7 +343,7 @@ public class ZLMHttpHookListener { | @@ -343,7 +343,7 @@ public class ZLMHttpHookListener { | ||
| 343 | } | 343 | } |
| 344 | // 开启语音对讲通道 | 344 | // 开启语音对讲通道 |
| 345 | try { | 345 | try { |
| 346 | - playService.audioBroadcastCmd(device, channelId, 60, (msg)->{ | 346 | + playService.audioBroadcastCmd(device, channelId, mediaInfo, 60, (msg)->{ |
| 347 | logger.info("[语音对讲] 通道建立成功, device: {}, channel: {}", deviceId, channelId); | 347 | logger.info("[语音对讲] 通道建立成功, device: {}, channel: {}", deviceId, channelId); |
| 348 | }); | 348 | }); |
| 349 | } catch (InvalidArgumentException | ParseException | SipException e) { | 349 | } catch (InvalidArgumentException | ParseException | SipException e) { |
| @@ -360,62 +360,30 @@ public class ZLMHttpHookListener { | @@ -360,62 +360,30 @@ public class ZLMHttpHookListener { | ||
| 360 | } | 360 | } |
| 361 | }else if ("talk".equals(param.getApp())){ | 361 | }else if ("talk".equals(param.getApp())){ |
| 362 | // 语音对讲推流 stream需要满足格式deviceId_channelId | 362 | // 语音对讲推流 stream需要满足格式deviceId_channelId |
| 363 | - if (param.isRegist() && param.getStream().indexOf("_") > 0) { | ||
| 364 | - String[] streamArray = param.getStream().split("_"); | ||
| 365 | - if (streamArray.length == 2) { | ||
| 366 | - String deviceId = streamArray[0]; | ||
| 367 | - String channelId = streamArray[1]; | ||
| 368 | - Device device = deviceService.getDevice(deviceId); | ||
| 369 | - if (device != null) { | ||
| 370 | - DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); | ||
| 371 | - if (deviceChannel != null) { | ||
| 372 | - if (audioBroadcastManager.exit(deviceId, channelId)) { | ||
| 373 | - // 直接推流 | ||
| 374 | - SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, param.getStream(), null); | ||
| 375 | - if (sendRtpItem == null) { | ||
| 376 | - // TODO 可能数据错误,重新开启语音通道 | ||
| 377 | - }else { | ||
| 378 | - MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | ||
| 379 | - logger.info("rtp/{}开始向上级推流, 目标={}:{},SSRC={}", sendRtpItem.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc()); | ||
| 380 | - Map<String, Object> sendParam = new HashMap<>(12); | ||
| 381 | - sendParam.put("vhost","__defaultVhost__"); | ||
| 382 | - sendParam.put("app",sendRtpItem.getApp()); | ||
| 383 | - sendParam.put("stream",sendRtpItem.getStreamId()); | ||
| 384 | - sendParam.put("ssrc", sendRtpItem.getSsrc()); | ||
| 385 | - sendParam.put("src_port", sendRtpItem.getLocalPort()); | ||
| 386 | - sendParam.put("pt", sendRtpItem.getPt()); | ||
| 387 | - sendParam.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0"); | ||
| 388 | - sendParam.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0"); | ||
| 389 | - | ||
| 390 | - JSONObject jsonObject; | ||
| 391 | - if (sendRtpItem.isTcpActive()) { | ||
| 392 | - jsonObject = zlmrtpServerFactory.startSendRtpPassive(mediaInfo, sendParam); | ||
| 393 | - } else { | ||
| 394 | - sendParam.put("is_udp", sendRtpItem.isTcp() ? "0" : "1"); | ||
| 395 | - sendParam.put("dst_url", sendRtpItem.getIp()); | ||
| 396 | - sendParam.put("dst_port", sendRtpItem.getPort()); | ||
| 397 | - jsonObject = zlmrtpServerFactory.startSendRtpStream(mediaInfo, sendParam); | ||
| 398 | - } | ||
| 399 | - if (jsonObject != null && jsonObject.getInteger("code") == 0) { | ||
| 400 | - logger.info("[语音对讲] 自动推流成功, device: {}, channel: {}", deviceId, channelId); | ||
| 401 | - } | ||
| 402 | - } | ||
| 403 | - }else { | ||
| 404 | - // 开启语音对讲通道 | ||
| 405 | - MediaServerItem mediaServerItem = mediaServerService.getOne(param.getMediaServerId()); | ||
| 406 | - playService.talk(mediaServerItem, device, channelId, (mediaServer, jsonObject)->{ | ||
| 407 | - System.out.println("开始推流"); | ||
| 408 | - }, eventResult -> { | ||
| 409 | - System.out.println(eventResult.msg); | ||
| 410 | - }, ()->{ | ||
| 411 | - System.out.println("超时"); | ||
| 412 | - }); | ||
| 413 | - } | ||
| 414 | - | ||
| 415 | - } | ||
| 416 | - } | ||
| 417 | - } | ||
| 418 | - } | 363 | + if (param.getStream().indexOf("_") > 0) { |
| 364 | + String[] streamArray = param.getStream().split("_"); | ||
| 365 | + if (streamArray.length == 2) { | ||
| 366 | + String deviceId = streamArray[0]; | ||
| 367 | + String channelId = streamArray[1]; | ||
| 368 | + Device device = deviceService.getDevice(deviceId); | ||
| 369 | + if (device != null) { | ||
| 370 | + if (param.isRegist()) { | ||
| 371 | + if (audioBroadcastManager.exit(deviceId, channelId)) { | ||
| 372 | + playService.stopAudioBroadcast(deviceId, channelId); | ||
| 373 | + } | ||
| 374 | + // 开启语音对讲通道 | ||
| 375 | + playService.talkCmd(device, channelId, mediaInfo, param.getStream(), (msg)->{ | ||
| 376 | + logger.info("[语音对讲] 通道建立成功, device: {}, channel: {}", deviceId, channelId); | ||
| 377 | + }); | ||
| 378 | + }else { | ||
| 379 | + // 流注销 | ||
| 380 | + playService.stopTalk(device, channelId, param.isRegist()); | ||
| 381 | + } | ||
| 382 | + } else{ | ||
| 383 | + logger.info("[语音对讲] 未找到设备:{}", deviceId); | ||
| 384 | + } | ||
| 385 | + } | ||
| 386 | + } | ||
| 419 | 387 | ||
| 420 | }else{ | 388 | }else{ |
| 421 | if (!"rtp".equals(param.getApp())){ | 389 | if (!"rtp".equals(param.getApp())){ |
| @@ -475,16 +443,21 @@ public class ZLMHttpHookListener { | @@ -475,16 +443,21 @@ public class ZLMHttpHookListener { | ||
| 475 | ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId); | 443 | ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId); |
| 476 | Device device = deviceService.getDevice(platformId); | 444 | Device device = deviceService.getDevice(platformId); |
| 477 | 445 | ||
| 478 | - try { | 446 | + |
| 479 | if (platform != null) { | 447 | if (platform != null) { |
| 480 | - commanderFroPlatform.streamByeCmd(platform, sendRtpItem); | 448 | + try { |
| 449 | + commanderFroPlatform.streamByeCmd(platform, sendRtpItem); | ||
| 450 | + } catch (SipException | InvalidArgumentException | ParseException e) { | ||
| 451 | + logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage()); | ||
| 452 | + } | ||
| 481 | } else { | 453 | } else { |
| 482 | - cmder.streamByeCmd(device, sendRtpItem.getChannelId(), param.getStream(), sendRtpItem.getCallId()); | 454 | + try { |
| 455 | + cmder.streamByeCmd(device, sendRtpItem.getChannelId(), param.getStream(), sendRtpItem.getCallId()); | ||
| 456 | + } catch (SipException | InvalidArgumentException | ParseException | | ||
| 457 | + SsrcTransactionNotFoundException e) { | ||
| 458 | + logger.error("[命令发送失败] 发送BYE: {}", e.getMessage()); | ||
| 459 | + } | ||
| 483 | } | 460 | } |
| 484 | - } catch (SipException | InvalidArgumentException | ParseException | | ||
| 485 | - SsrcTransactionNotFoundException e) { | ||
| 486 | - logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage()); | ||
| 487 | - } | ||
| 488 | } | 461 | } |
| 489 | } | 462 | } |
| 490 | } | 463 | } |
| @@ -527,7 +500,7 @@ public class ZLMHttpHookListener { | @@ -527,7 +500,7 @@ public class ZLMHttpHookListener { | ||
| 527 | logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage()); | 500 | logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage()); |
| 528 | } | 501 | } |
| 529 | redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(), | 502 | redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(), |
| 530 | - sendRtpItem.getCallId(), sendRtpItem.getStreamId()); | 503 | + sendRtpItem.getCallId(), sendRtpItem.getStream()); |
| 531 | } | 504 | } |
| 532 | } | 505 | } |
| 533 | } | 506 | } |
| @@ -556,8 +529,7 @@ public class ZLMHttpHookListener { | @@ -556,8 +529,7 @@ public class ZLMHttpHookListener { | ||
| 556 | try { | 529 | try { |
| 557 | cmder.streamByeCmd(device, streamInfoForPlayBackCatch.getChannelId(), | 530 | cmder.streamByeCmd(device, streamInfoForPlayBackCatch.getChannelId(), |
| 558 | streamInfoForPlayBackCatch.getStream(), null); | 531 | streamInfoForPlayBackCatch.getStream(), null); |
| 559 | - } catch (InvalidArgumentException | ParseException | SipException | | ||
| 560 | - SsrcTransactionNotFoundException e) { | 532 | + } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) { |
| 561 | logger.error("[无人观看]回放, 发送BYE失败 {}", e.getMessage()); | 533 | logger.error("[无人观看]回放, 发送BYE失败 {}", e.getMessage()); |
| 562 | } | 534 | } |
| 563 | } | 535 | } |
| @@ -573,6 +545,13 @@ public class ZLMHttpHookListener { | @@ -573,6 +545,13 @@ public class ZLMHttpHookListener { | ||
| 573 | ret.put("close", false); | 545 | ret.put("close", false); |
| 574 | return ret; | 546 | return ret; |
| 575 | } | 547 | } |
| 548 | + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, param.getStream(), null); | ||
| 549 | + if ("talk".equals(sendRtpItem.getApp())){ | ||
| 550 | + ret.put("close", false); | ||
| 551 | + return ret; | ||
| 552 | + } | ||
| 553 | + }else if ("talk".equals(param.getApp()) || "broadcast".equals(param.getApp())){ | ||
| 554 | + ret.put("close", false); | ||
| 576 | } else { | 555 | } else { |
| 577 | // 非国标流 推流/拉流代理 | 556 | // 非国标流 推流/拉流代理 |
| 578 | // 拉流代理 | 557 | // 拉流代理 |
| @@ -734,7 +713,7 @@ public class ZLMHttpHookListener { | @@ -734,7 +713,7 @@ public class ZLMHttpHookListener { | ||
| 734 | logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage()); | 713 | logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage()); |
| 735 | } | 714 | } |
| 736 | redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(), | 715 | redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(), |
| 737 | - sendRtpItem.getCallId(), sendRtpItem.getStreamId()); | 716 | + sendRtpItem.getCallId(), sendRtpItem.getStream()); |
| 738 | } | 717 | } |
| 739 | } | 718 | } |
| 740 | }); | 719 | }); |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java
| @@ -291,6 +291,10 @@ public class ZLMRESTfulUtils { | @@ -291,6 +291,10 @@ public class ZLMRESTfulUtils { | ||
| 291 | return sendPost(mediaServerItem, "startSendRtpPassive",param, null); | 291 | return sendPost(mediaServerItem, "startSendRtpPassive",param, null); |
| 292 | } | 292 | } |
| 293 | 293 | ||
| 294 | + public JSONObject startSendRtpPassive(MediaServerItem mediaServerItem, Map<String, Object> param, RequestCallback callback) { | ||
| 295 | + return sendPost(mediaServerItem, "startSendRtpPassive",param, callback); | ||
| 296 | + } | ||
| 297 | + | ||
| 294 | public JSONObject stopSendRtp(MediaServerItem mediaServerItem, Map<String, Object> param) { | 298 | public JSONObject stopSendRtp(MediaServerItem mediaServerItem, Map<String, Object> param) { |
| 295 | return sendPost(mediaServerItem, "stopSendRtp",param, null); | 299 | return sendPost(mediaServerItem, "stopSendRtp",param, null); |
| 296 | } | 300 | } |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
| @@ -229,7 +229,7 @@ public class ZLMRTPServerFactory { | @@ -229,7 +229,7 @@ public class ZLMRTPServerFactory { | ||
| 229 | sendRtpItem.setPort(port); | 229 | sendRtpItem.setPort(port); |
| 230 | sendRtpItem.setSsrc(ssrc); | 230 | sendRtpItem.setSsrc(ssrc); |
| 231 | sendRtpItem.setApp(app); | 231 | sendRtpItem.setApp(app); |
| 232 | - sendRtpItem.setStreamId(stream); | 232 | + sendRtpItem.setStream(stream); |
| 233 | sendRtpItem.setPlatformId(platformId); | 233 | sendRtpItem.setPlatformId(platformId); |
| 234 | sendRtpItem.setChannelId(channelId); | 234 | sendRtpItem.setChannelId(channelId); |
| 235 | sendRtpItem.setTcp(tcp); | 235 | sendRtpItem.setTcp(tcp); |
| @@ -290,6 +290,10 @@ public class ZLMRTPServerFactory { | @@ -290,6 +290,10 @@ public class ZLMRTPServerFactory { | ||
| 290 | return zlmresTfulUtils.startSendRtpPassive(mediaServerItem, param); | 290 | return zlmresTfulUtils.startSendRtpPassive(mediaServerItem, param); |
| 291 | } | 291 | } |
| 292 | 292 | ||
| 293 | + public JSONObject startSendRtpPassive(MediaServerItem mediaServerItem, Map<String, Object>param, ZLMRESTfulUtils.RequestCallback callback) { | ||
| 294 | + return zlmresTfulUtils.startSendRtpPassive(mediaServerItem, param, callback); | ||
| 295 | + } | ||
| 296 | + | ||
| 293 | /** | 297 | /** |
| 294 | * 查询待转推的流是否就绪 | 298 | * 查询待转推的流是否就绪 |
| 295 | */ | 299 | */ |
| @@ -343,7 +347,7 @@ public class ZLMRTPServerFactory { | @@ -343,7 +347,7 @@ public class ZLMRTPServerFactory { | ||
| 343 | result= true; | 347 | result= true; |
| 344 | logger.info("[停止RTP推流] 成功"); | 348 | logger.info("[停止RTP推流] 成功"); |
| 345 | } else { | 349 | } else { |
| 346 | - logger.error("[停止RTP推流] 失败: {}, 参数:{}->\r\n{}",jsonObject.getString("msg"), JSON.toJSON(param), jsonObject); | 350 | + logger.warn("[停止RTP推流] 失败: {}, 参数:{}->\r\n{}",jsonObject.getString("msg"), JSON.toJSON(param), jsonObject); |
| 347 | } | 351 | } |
| 348 | return result; | 352 | return result; |
| 349 | } | 353 | } |
src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
| @@ -11,10 +11,8 @@ import com.genersoft.iot.vmp.service.bean.InviteTimeOutCallback; | @@ -11,10 +11,8 @@ import com.genersoft.iot.vmp.service.bean.InviteTimeOutCallback; | ||
| 11 | import com.genersoft.iot.vmp.service.bean.PlayBackCallback; | 11 | import com.genersoft.iot.vmp.service.bean.PlayBackCallback; |
| 12 | import com.genersoft.iot.vmp.service.bean.SSRCInfo; | 12 | import com.genersoft.iot.vmp.service.bean.SSRCInfo; |
| 13 | import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; | 13 | import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; |
| 14 | -import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent; | ||
| 15 | -import com.genersoft.iot.vmp.vmanager.bean.WVPResult; | 14 | +import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioEvent; |
| 16 | import gov.nist.javax.sip.message.SIPResponse; | 15 | import gov.nist.javax.sip.message.SIPResponse; |
| 17 | -import org.springframework.web.context.request.async.DeferredResult; | ||
| 18 | 16 | ||
| 19 | import javax.sip.InvalidArgumentException; | 17 | import javax.sip.InvalidArgumentException; |
| 20 | import javax.sip.SipException; | 18 | import javax.sip.SipException; |
| @@ -29,10 +27,6 @@ public interface IPlayService { | @@ -29,10 +27,6 @@ public interface IPlayService { | ||
| 29 | 27 | ||
| 30 | void onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId); | 28 | void onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId); |
| 31 | 29 | ||
| 32 | - void talk(MediaServerItem mediaServerItem, Device device, String channelId, | ||
| 33 | - ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, | ||
| 34 | - Runnable timeoutCallback); | ||
| 35 | - | ||
| 36 | void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, | 30 | void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, |
| 37 | ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, | 31 | ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, |
| 38 | InviteTimeOutCallback timeoutCallback); | 32 | InviteTimeOutCallback timeoutCallback); |
| @@ -62,7 +56,7 @@ public interface IPlayService { | @@ -62,7 +56,7 @@ public interface IPlayService { | ||
| 62 | AudioBroadcastResult audioBroadcast(Device device, String channelId); | 56 | AudioBroadcastResult audioBroadcast(Device device, String channelId); |
| 63 | void stopAudioBroadcast(String deviceId, String channelId); | 57 | void stopAudioBroadcast(String deviceId, String channelId); |
| 64 | 58 | ||
| 65 | - void audioBroadcastCmd(Device device, String channelId, int timeout, AudioBroadcastEvent event) throws InvalidArgumentException, ParseException, SipException; | 59 | + void audioBroadcastCmd(Device device, String channelId, MediaServerItem mediaServerItem, int timeout, AudioEvent event) throws InvalidArgumentException, ParseException, SipException; |
| 66 | 60 | ||
| 67 | void pauseRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException; | 61 | void pauseRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException; |
| 68 | 62 | ||
| @@ -72,4 +66,8 @@ public interface IPlayService { | @@ -72,4 +66,8 @@ public interface IPlayService { | ||
| 72 | 66 | ||
| 73 | void startSendRtpStreamHand(SendRtpItem sendRtpItem, ParentPlatform parentPlatform, | 67 | void startSendRtpStreamHand(SendRtpItem sendRtpItem, ParentPlatform parentPlatform, |
| 74 | JSONObject jsonObject, Map<String, Object> param, CallIdHeader callIdHeader); | 68 | JSONObject jsonObject, Map<String, Object> param, CallIdHeader callIdHeader); |
| 69 | + | ||
| 70 | + void talkCmd(Device device, String channelId, MediaServerItem mediaServerItem, String stream, AudioEvent event); | ||
| 71 | + | ||
| 72 | + void stopTalk(Device device, String channelId, Boolean streamIsReady); | ||
| 75 | } | 73 | } |
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
| @@ -202,7 +202,7 @@ public class DeviceServiceImpl implements IDeviceService { | @@ -202,7 +202,7 @@ public class DeviceServiceImpl implements IDeviceService { | ||
| 202 | Map<String, Object> param = new HashMap<>(); | 202 | Map<String, Object> param = new HashMap<>(); |
| 203 | param.put("vhost", "__defaultVhost__"); | 203 | param.put("vhost", "__defaultVhost__"); |
| 204 | param.put("app", sendRtpItem.getApp()); | 204 | param.put("app", sendRtpItem.getApp()); |
| 205 | - param.put("stream", sendRtpItem.getStreamId()); | 205 | + param.put("stream", sendRtpItem.getStream()); |
| 206 | zlmresTfulUtils.stopSendRtp(mediaInfo, param); | 206 | zlmresTfulUtils.stopSendRtp(mediaInfo, param); |
| 207 | } | 207 | } |
| 208 | 208 |
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java
| @@ -253,7 +253,7 @@ public class PlatformServiceImpl implements IPlatformService { | @@ -253,7 +253,7 @@ public class PlatformServiceImpl implements IPlatformService { | ||
| 253 | Map<String, Object> param = new HashMap<>(3); | 253 | Map<String, Object> param = new HashMap<>(3); |
| 254 | param.put("vhost", "__defaultVhost__"); | 254 | param.put("vhost", "__defaultVhost__"); |
| 255 | param.put("app", sendRtpItem.getApp()); | 255 | param.put("app", sendRtpItem.getApp()); |
| 256 | - param.put("stream", sendRtpItem.getStreamId()); | 256 | + param.put("stream", sendRtpItem.getStream()); |
| 257 | zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param); | 257 | zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param); |
| 258 | } | 258 | } |
| 259 | } | 259 | } |
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
| @@ -41,7 +41,7 @@ import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; | @@ -41,7 +41,7 @@ import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; | ||
| 41 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; | 41 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; |
| 42 | import com.genersoft.iot.vmp.vmanager.bean.StreamContent; | 42 | import com.genersoft.iot.vmp.vmanager.bean.StreamContent; |
| 43 | import com.genersoft.iot.vmp.vmanager.bean.WVPResult; | 43 | import com.genersoft.iot.vmp.vmanager.bean.WVPResult; |
| 44 | -import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent; | 44 | +import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioEvent; |
| 45 | import gov.nist.javax.sip.message.SIPResponse; | 45 | import gov.nist.javax.sip.message.SIPResponse; |
| 46 | import org.slf4j.Logger; | 46 | import org.slf4j.Logger; |
| 47 | import org.slf4j.LoggerFactory; | 47 | import org.slf4j.LoggerFactory; |
| @@ -134,8 +134,8 @@ public class PlayServiceImpl implements IPlayService { | @@ -134,8 +134,8 @@ public class PlayServiceImpl implements IPlayService { | ||
| 134 | 134 | ||
| 135 | @Override | 135 | @Override |
| 136 | public void play(MediaServerItem mediaServerItem, String deviceId, String channelId, | 136 | public void play(MediaServerItem mediaServerItem, String deviceId, String channelId, |
| 137 | - ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, | ||
| 138 | - Runnable timeoutCallback) { | 137 | + ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, |
| 138 | + Runnable timeoutCallback) { | ||
| 139 | if (mediaServerItem == null) { | 139 | if (mediaServerItem == null) { |
| 140 | throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到可用的zlm"); | 140 | throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到可用的zlm"); |
| 141 | } | 141 | } |
| @@ -243,194 +243,148 @@ public class PlayServiceImpl implements IPlayService { | @@ -243,194 +243,148 @@ public class PlayServiceImpl implements IPlayService { | ||
| 243 | } | 243 | } |
| 244 | } | 244 | } |
| 245 | 245 | ||
| 246 | - @Override | ||
| 247 | - public void talk(MediaServerItem mediaServerItem, Device device, String channelId, | ||
| 248 | - ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, | ||
| 249 | - Runnable timeoutCallback) { | ||
| 250 | - String streamId = null; | ||
| 251 | - if (mediaServerItem.isRtpEnable()) { | ||
| 252 | - streamId = String.format("%s_%s", device.getDeviceId(), channelId); | 246 | + private void talk(MediaServerItem mediaServerItem, Device device, String channelId, String stream, |
| 247 | + ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, | ||
| 248 | + Runnable timeoutCallback, AudioEvent audioEvent) { | ||
| 249 | + | ||
| 250 | + String playSsrc = mediaServerItem.getSsrcConfig().getPlaySsrc(); | ||
| 251 | + if (playSsrc == null) { | ||
| 252 | + audioEvent.call("ssrc已经用尽"); | ||
| 253 | + return; | ||
| 254 | + } | ||
| 255 | + SendRtpItem sendRtpItem = new SendRtpItem(); | ||
| 256 | + sendRtpItem.setApp("talk"); | ||
| 257 | + sendRtpItem.setStream(stream); | ||
| 258 | + sendRtpItem.setSsrc(playSsrc); | ||
| 259 | + sendRtpItem.setDeviceId(device.getDeviceId()); | ||
| 260 | + sendRtpItem.setPlatformId(device.getDeviceId()); | ||
| 261 | + sendRtpItem.setChannelId(channelId); | ||
| 262 | + sendRtpItem.setRtcp(false); | ||
| 263 | + sendRtpItem.setMediaServerId(mediaServerItem.getId()); | ||
| 264 | + sendRtpItem.setOnlyAudio(true); | ||
| 265 | + sendRtpItem.setPlayType(InviteStreamType.TALK); | ||
| 266 | + sendRtpItem.setPt(8); | ||
| 267 | + sendRtpItem.setStatus(1); | ||
| 268 | + sendRtpItem.setTcpActive(false); | ||
| 269 | + sendRtpItem.setTcp(true); | ||
| 270 | + sendRtpItem.setUsePs(false); | ||
| 271 | + sendRtpItem.setReceiveStream(stream); | ||
| 272 | + | ||
| 273 | + | ||
| 274 | + int port = zlmrtpServerFactory.keepPort(mediaServerItem, playSsrc); | ||
| 275 | + //端口获取失败的ssrcInfo 没有必要发送点播指令 | ||
| 276 | + if (port <= 0) { | ||
| 277 | + logger.info("[语音对讲] 端口分配异常,deviceId={},channelId={}", device.getDeviceId(), channelId); | ||
| 278 | + audioEvent.call("端口分配异常"); | ||
| 279 | + return; | ||
| 253 | } | 280 | } |
| 254 | - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, device.isSsrcCheck(), false); | ||
| 255 | - logger.info("[对讲开始] deviceId: {}, channelId: {},收流端口: {}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, ssrcInfo.getPort(), device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); | 281 | + sendRtpItem.setLocalPort(port); |
| 282 | + sendRtpItem.setPort(port); | ||
| 283 | + logger.info("[语音对讲]开始 deviceId: {}, channelId: {},收流端口: {}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, sendRtpItem.getLocalPort(), device.getStreamMode(), sendRtpItem.getSsrc(), false); | ||
| 256 | // 超时处理 | 284 | // 超时处理 |
| 257 | String timeOutTaskKey = UUID.randomUUID().toString(); | 285 | String timeOutTaskKey = UUID.randomUUID().toString(); |
| 258 | - SSRCInfo finalSsrcInfo = ssrcInfo; | ||
| 259 | - System.out.println("设置超时任务: " + timeOutTaskKey); | ||
| 260 | dynamicTask.startDelay(timeOutTaskKey, () -> { | 286 | dynamicTask.startDelay(timeOutTaskKey, () -> { |
| 261 | 287 | ||
| 262 | - logger.info("[对讲超时] 收流超时 deviceId: {}, channelId: {},端口:{}, SSRC: {}", device.getDeviceId(), channelId, finalSsrcInfo.getPort(), finalSsrcInfo.getSsrc()); | 288 | + logger.info("[语音对讲] 收流超时 deviceId: {}, channelId: {},端口:{}, SSRC: {}", device.getDeviceId(), channelId, sendRtpItem.getPort(), sendRtpItem.getSsrc()); |
| 263 | timeoutCallback.run(); | 289 | timeoutCallback.run(); |
| 264 | // 点播超时回复BYE 同时释放ssrc以及此次点播的资源 | 290 | // 点播超时回复BYE 同时释放ssrc以及此次点播的资源 |
| 265 | try { | 291 | try { |
| 266 | - cmder.streamByeCmd(device, channelId, finalSsrcInfo.getStream(), null); | ||
| 267 | - } catch (InvalidArgumentException | ParseException | SipException e) { | ||
| 268 | - logger.error("[对讲超时], 发送BYE失败 {}", e.getMessage()); | ||
| 269 | - } catch (SsrcTransactionNotFoundException e) { | 292 | + cmder.streamByeCmd(device, channelId, sendRtpItem.getStream(), null); |
| 293 | + } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) { | ||
| 294 | + logger.error("[语音对讲]超时, 发送BYE失败 {}", e.getMessage()); | ||
| 295 | + } finally { | ||
| 270 | timeoutCallback.run(); | 296 | timeoutCallback.run(); |
| 271 | - mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc()); | ||
| 272 | - mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream()); | ||
| 273 | - streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream()); | 297 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc()); |
| 298 | + streamSession.remove(device.getDeviceId(), channelId, sendRtpItem.getStream()); | ||
| 274 | } | 299 | } |
| 275 | }, userSetting.getPlayTimeout()); | 300 | }, userSetting.getPlayTimeout()); |
| 276 | - final String ssrc = ssrcInfo.getSsrc(); | ||
| 277 | - final String stream = ssrcInfo.getStream(); | ||
| 278 | - //端口获取失败的ssrcInfo 没有必要发送点播指令 | ||
| 279 | - if (ssrcInfo.getPort() <= 0) { | ||
| 280 | - logger.info("[对讲] 端口分配异常,deviceId={},channelId={},ssrcInfo={}", device.getDeviceId(), channelId, ssrcInfo); | ||
| 281 | - return; | ||
| 282 | - } | ||
| 283 | 301 | ||
| 284 | String callId = SipUtils.getNewCallId(); | 302 | String callId = SipUtils.getNewCallId(); |
| 285 | - boolean pushing = false; | ||
| 286 | - // 查看设备是否已经在推流 | ||
| 287 | -// MediaItem mediaItem = zlmrtpServerFactory.getMediaInfo(mediaServerItem, "rtp",ssrcInfo.getStream()); | ||
| 288 | -// if (mediaItem != null) { | ||
| 289 | -// SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, | ||
| 290 | -// mediaItem.getOriginSock().getPeer_ip(), mediaItem.getOriginSock().getPeer_port(), ssrcInfo.getSsrc(), device.getDeviceId(), | ||
| 291 | -// device.getDeviceId(), channelId, | ||
| 292 | -// false); | ||
| 293 | -// | ||
| 294 | -// sendRtpItem.setTcpActive(false); | ||
| 295 | -// sendRtpItem.setCallId(callId); | ||
| 296 | -// sendRtpItem.setPlayType(InviteStreamType.TALK); | ||
| 297 | -// sendRtpItem.setStatus(1); | ||
| 298 | -// sendRtpItem.setIp(mediaItem.getOriginSock().getPeer_ip()); | ||
| 299 | -// sendRtpItem.setPort(mediaItem.getOriginSock().getPeer_port()); | ||
| 300 | -// sendRtpItem.setTcpActive(false); | ||
| 301 | -// sendRtpItem.setStreamId(ssrcInfo.getStream()); | ||
| 302 | -// sendRtpItem.setApp("1000"); | ||
| 303 | -// sendRtpItem.setStreamId("1000"); | ||
| 304 | -// sendRtpItem.setSsrc(ssrc); | ||
| 305 | -// sendRtpItem.setOnlyAudio(true); | ||
| 306 | -// redisCatchStorage.updateSendRTPSever(sendRtpItem); | ||
| 307 | -// | ||
| 308 | -// Map<String, Object> param = new HashMap<>(12); | ||
| 309 | -// param.put("vhost","__defaultVhost__"); | ||
| 310 | -// param.put("app",sendRtpItem.getApp()); | ||
| 311 | -// param.put("stream",sendRtpItem.getStreamId()); | ||
| 312 | -// param.put("ssrc", sendRtpItem.getSsrc()); | ||
| 313 | -// param.put("dst_url", sendRtpItem.getIp()); | ||
| 314 | -// param.put("dst_port", sendRtpItem.getPort()); | ||
| 315 | -// param.put("src_port", sendRtpItem.getLocalPort()); | ||
| 316 | -// param.put("pt", sendRtpItem.getPt()); | ||
| 317 | -// param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0"); | ||
| 318 | -// param.put("is_udp", sendRtpItem.isTcp() ? "0" : "1"); | ||
| 319 | -// param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0"); | ||
| 320 | -// JSONObject jsonObject = zlmrtpServerFactory.startSendRtpStream(mediaServerItem, param); | ||
| 321 | -// System.out.println(2222); | ||
| 322 | -// System.out.println(jsonObject); | ||
| 323 | -// }else { | ||
| 324 | - try { | ||
| 325 | - cmder.talkStreamCmd(mediaServerItem, ssrcInfo, device, channelId, callId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> { | ||
| 326 | - logger.info("[对讲] 流已生成, 开始推流: " + response.toJSONString()); | ||
| 327 | - dynamicTask.stop(timeOutTaskKey); | ||
| 328 | - // TODO 暂不做处理 | ||
| 329 | - }, (MediaServerItem mediaServerItemInuse, JSONObject json) -> { | ||
| 330 | - logger.info("[对讲] 设备开始推流: " + json.toJSONString()); | ||
| 331 | - dynamicTask.stop(timeOutTaskKey); | ||
| 332 | - // 获取远程IP端口 作为回复语音流的地址 | ||
| 333 | - String ip = json.getString("ip"); | ||
| 334 | - Integer port = json.getInteger("port"); | ||
| 335 | - logger.info("[设备开始推流]{}/{}, 来自ip:{}, 端口:{}", device.getDeviceId(), channelId, ip, port); | ||
| 336 | - // 查看平台推流是否就绪 | ||
| 337 | -// Boolean ready = zlmrtpServerFactory.isStreamReady(mediaServerItemInuse, "talk", stream); | ||
| 338 | -// if (!ready) { | ||
| 339 | -// try { | ||
| 340 | -// cmder.streamByeCmd(device, channelId, finalSsrcInfo.getStream(), null); | ||
| 341 | -// } catch (InvalidArgumentException | ParseException | SipException e) { | ||
| 342 | -// logger.error("[对讲超时], 发送BYE失败 {}", e.getMessage()); | ||
| 343 | -// } catch (SsrcTransactionNotFoundException e) { | ||
| 344 | -// timeoutCallback.run(); | ||
| 345 | -// mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc()); | ||
| 346 | -// mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream()); | ||
| 347 | -// streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream()); | ||
| 348 | -// } | ||
| 349 | -// }else { | ||
| 350 | -// try { | ||
| 351 | -// Thread.sleep(1000); | ||
| 352 | -// } catch (InterruptedException e) { | ||
| 353 | -// throw new RuntimeException(e); | ||
| 354 | -// } | ||
| 355 | - SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, ip, port, ssrcInfo.getSsrc(), device.getDeviceId(), | ||
| 356 | - device.getDeviceId(), channelId, | ||
| 357 | - false, false); | ||
| 358 | - | ||
| 359 | - | ||
| 360 | -// if (sendRtpItem.getLocalPort() == 0) { | ||
| 361 | -// logger.warn("服务器端口资源不足"); | ||
| 362 | -// try { | ||
| 363 | -// cmder.streamByeCmd(device, channelId, finalSsrcInfo.getStream(), null); | ||
| 364 | -// } catch (InvalidArgumentException | ParseException | SipException e) { | ||
| 365 | -// logger.error("[对讲超时], 发送BYE失败 {}", e.getMessage()); | ||
| 366 | -// } catch (SsrcTransactionNotFoundException e) { | ||
| 367 | -// timeoutCallback.run(); | ||
| 368 | -// mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc()); | ||
| 369 | -// mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream()); | ||
| 370 | -// streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream()); | ||
| 371 | -// } | ||
| 372 | -// return; | ||
| 373 | -// } | ||
| 374 | - sendRtpItem.setTcpActive(false); | ||
| 375 | - sendRtpItem.setCallId(callId); | ||
| 376 | - sendRtpItem.setPlayType(InviteStreamType.TALK); | ||
| 377 | - sendRtpItem.setStatus(1); | ||
| 378 | - sendRtpItem.setIp(ip); | ||
| 379 | - sendRtpItem.setPort(port); | ||
| 380 | - sendRtpItem.setTcpActive(false); | ||
| 381 | - sendRtpItem.setApp("1000"); | ||
| 382 | - sendRtpItem.setStreamId("1000"); | ||
| 383 | - sendRtpItem.setSsrc(ssrc); | ||
| 384 | - sendRtpItem.setOnlyAudio(true); | ||
| 385 | - sendRtpItem.setRtcp(false); | ||
| 386 | - redisCatchStorage.updateSendRTPSever(sendRtpItem); | ||
| 387 | 303 | ||
| 388 | - Map<String, Object> param = new HashMap<>(12); | ||
| 389 | - param.put("vhost","__defaultVhost__"); | ||
| 390 | - param.put("app",sendRtpItem.getApp()); | ||
| 391 | - param.put("stream",sendRtpItem.getStreamId()); | ||
| 392 | - param.put("ssrc", sendRtpItem.getSsrc()); | ||
| 393 | - param.put("dst_url", sendRtpItem.getIp()); | ||
| 394 | - param.put("dst_port", sendRtpItem.getPort()); | ||
| 395 | - param.put("src_port", sendRtpItem.getLocalPort()); | ||
| 396 | - param.put("pt", sendRtpItem.getPt()); | ||
| 397 | - param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0"); | ||
| 398 | - param.put("is_udp", sendRtpItem.isTcp() ? "0" : "1"); | ||
| 399 | - param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0"); | ||
| 400 | - JSONObject jsonObject = zlmrtpServerFactory.startSendRtpStream(mediaServerItemInuse, param); | ||
| 401 | - System.out.println(11111); | ||
| 402 | - System.out.println(sendRtpItem.getIp() + ":" + sendRtpItem.getPort()); | ||
| 403 | -// System.out.println(jsonObject); | ||
| 404 | -// } | 304 | + zlmrtpServerFactory.releasePort(mediaServerItem, playSsrc); |
| 305 | + Map<String, Object> param = new HashMap<>(12); | ||
| 306 | + param.put("vhost","__defaultVhost__"); | ||
| 307 | + param.put("app", sendRtpItem.getApp()); | ||
| 308 | + param.put("stream", sendRtpItem.getStream()); | ||
| 309 | + param.put("ssrc", sendRtpItem.getSsrc()); | ||
| 310 | + param.put("src_port", sendRtpItem.getLocalPort()); | ||
| 311 | + param.put("pt", sendRtpItem.getPt()); | ||
| 312 | + param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0"); | ||
| 313 | + param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0"); | ||
| 314 | + param.put("is_udp", sendRtpItem.isTcp() ? "0" : "1"); | ||
| 315 | + param.put("recv_stream_id", sendRtpItem.getReceiveStream()); | ||
| 316 | + param.put("close_delay_ms", userSetting.getPlayTimeout() * 1000); | ||
| 317 | + | ||
| 318 | + zlmrtpServerFactory.startSendRtpPassive(mediaServerItem, param, jsonObject -> { | ||
| 319 | + if (jsonObject == null || jsonObject.getInteger("code") != 0 ) { | ||
| 320 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc()); | ||
| 321 | + logger.info("[语音对讲]失败 deviceId: {}, channelId: {}", device.getDeviceId(), channelId); | ||
| 322 | + audioEvent.call("失败, " + jsonObject.getString("msg")); | ||
| 323 | + // 查看是否已经建立了通道,存在则发送bye | ||
| 324 | + stopTalk(device, channelId); | ||
| 325 | + } | ||
| 326 | + }); | ||
| 405 | 327 | ||
| 406 | - }, (event) -> { | ||
| 407 | 328 | ||
| 408 | - }, (event) -> { | ||
| 409 | - dynamicTask.stop(timeOutTaskKey); | ||
| 410 | - mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream()); | ||
| 411 | - // 释放ssrc | ||
| 412 | - mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc()); | 329 | + // 查看设备是否已经在推流 |
| 330 | + try { | ||
| 331 | + cmder.talkStreamCmd(mediaServerItem, sendRtpItem, device, channelId, callId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> { | ||
| 332 | + logger.info("[语音对讲] 流已生成, 开始推流: " + response.toJSONString()); | ||
| 333 | + dynamicTask.stop(timeOutTaskKey); | ||
| 334 | + // TODO 暂不做处理 | ||
| 335 | + }, (MediaServerItem mediaServerItemInuse, JSONObject json) -> { | ||
| 336 | + logger.info("[语音对讲] 设备开始推流: " + json.toJSONString()); | ||
| 337 | + dynamicTask.stop(timeOutTaskKey); | ||
| 413 | 338 | ||
| 414 | - streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream()); | ||
| 415 | - errorEvent.response(event); | ||
| 416 | - }); | ||
| 417 | - } catch (InvalidArgumentException | SipException | ParseException e) { | 339 | + }, (event) -> { |
| 340 | + dynamicTask.stop(timeOutTaskKey); | ||
| 341 | + | ||
| 342 | + if (event.event instanceof ResponseEvent) { | ||
| 343 | + ResponseEvent responseEvent = (ResponseEvent) event.event; | ||
| 344 | + if (responseEvent.getResponse() instanceof SIPResponse) { | ||
| 345 | + SIPResponse response = (SIPResponse) responseEvent.getResponse(); | ||
| 346 | + sendRtpItem.setFromTag(response.getFromTag()); | ||
| 347 | + sendRtpItem.setToTag(response.getToTag()); | ||
| 348 | + sendRtpItem.setCallId(response.getCallIdHeader().getCallId()); | ||
| 349 | + redisCatchStorage.updateSendRTPSever(sendRtpItem); | ||
| 350 | + | ||
| 351 | + streamSession.put(device.getDeviceId(), channelId, response.getCallIdHeader().getCallId(), | ||
| 352 | + sendRtpItem.getStream(), sendRtpItem.getSsrc(), sendRtpItem.getMediaServerId(), | ||
| 353 | + response, VideoStreamSessionManager.SessionType.talk); | ||
| 354 | + } else { | ||
| 355 | + logger.error("[语音对讲]收到的消息错误,response不是SIPResponse"); | ||
| 356 | + } | ||
| 357 | + } else { | ||
| 358 | + logger.error("[语音对讲]收到的消息错误,event不是ResponseEvent"); | ||
| 359 | + } | ||
| 418 | 360 | ||
| 419 | - logger.error("[命令发送失败] 对讲消息: {}", e.getMessage()); | 361 | + }, (event) -> { |
| 420 | dynamicTask.stop(timeOutTaskKey); | 362 | dynamicTask.stop(timeOutTaskKey); |
| 421 | - mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream()); | 363 | + mediaServerService.closeRTPServer(mediaServerItem, sendRtpItem.getStream()); |
| 422 | // 释放ssrc | 364 | // 释放ssrc |
| 423 | - mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc()); | 365 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc()); |
| 366 | + streamSession.remove(device.getDeviceId(), channelId, sendRtpItem.getStream()); | ||
| 367 | + errorEvent.response(event); | ||
| 368 | + }); | ||
| 369 | + } catch (InvalidArgumentException | SipException | ParseException e) { | ||
| 424 | 370 | ||
| 425 | - streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream()); | ||
| 426 | - SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new CmdSendFailEvent(null)); | ||
| 427 | - eventResult.msg = "命令发送失败"; | ||
| 428 | - errorEvent.response(eventResult); | ||
| 429 | - } | 371 | + logger.error("[命令发送失败] 对讲消息: {}", e.getMessage()); |
| 372 | + dynamicTask.stop(timeOutTaskKey); | ||
| 373 | + mediaServerService.closeRTPServer(mediaServerItem, sendRtpItem.getStream()); | ||
| 374 | + // 释放ssrc | ||
| 375 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc()); | ||
| 376 | + | ||
| 377 | + streamSession.remove(device.getDeviceId(), channelId, sendRtpItem.getStream()); | ||
| 378 | + SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new CmdSendFailEvent(null)); | ||
| 379 | + eventResult.msg = "命令发送失败"; | ||
| 380 | + errorEvent.response(eventResult); | ||
| 381 | + } | ||
| 430 | // } | 382 | // } |
| 431 | 383 | ||
| 432 | } | 384 | } |
| 433 | 385 | ||
| 386 | + | ||
| 387 | + | ||
| 434 | @Override | 388 | @Override |
| 435 | public void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, | 389 | public void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, |
| 436 | ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, | 390 | ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, |
| @@ -446,7 +400,8 @@ public class PlayServiceImpl implements IPlayService { | @@ -446,7 +400,8 @@ public class PlayServiceImpl implements IPlayService { | ||
| 446 | // 点播超时回复BYE 同时释放ssrc以及此次点播的资源 | 400 | // 点播超时回复BYE 同时释放ssrc以及此次点播的资源 |
| 447 | try { | 401 | try { |
| 448 | cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null); | 402 | cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null); |
| 449 | - } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) { | 403 | + } catch (InvalidArgumentException | ParseException | SipException | |
| 404 | + SsrcTransactionNotFoundException e) { | ||
| 450 | logger.error("[点播超时], 发送BYE失败 {}", e.getMessage()); | 405 | logger.error("[点播超时], 发送BYE失败 {}", e.getMessage()); |
| 451 | } finally { | 406 | } finally { |
| 452 | timeoutCallback.run(1, "收流超时"); | 407 | timeoutCallback.run(1, "收流超时"); |
| @@ -483,7 +438,7 @@ public class PlayServiceImpl implements IPlayService { | @@ -483,7 +438,7 @@ public class PlayServiceImpl implements IPlayService { | ||
| 483 | onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId); | 438 | onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId); |
| 484 | hookEvent.response(mediaServerItemInuse, response); | 439 | hookEvent.response(mediaServerItemInuse, response); |
| 485 | logger.info("[点播成功] deviceId: {}, channelId: {}", device.getDeviceId(), channelId); | 440 | logger.info("[点播成功] deviceId: {}, channelId: {}", device.getDeviceId(), channelId); |
| 486 | - String streamUrl = String.format("http://127.0.0.1:%s/%s/%s.live.flv", mediaServerItemInuse.getHttpPort(), "rtp", ssrcInfo.getStream()); | 441 | + String streamUrl = String.format("http://127.0.0.1:%s/%s/%s.live.flv", mediaServerItemInuse.getHttpPort(), "rtp", ssrcInfo.getStream()); |
| 487 | String path = "snap"; | 442 | String path = "snap"; |
| 488 | String fileName = device.getDeviceId() + "_" + channelId + ".jpg"; | 443 | String fileName = device.getDeviceId() + "_" + channelId + ".jpg"; |
| 489 | // 请求截图 | 444 | // 请求截图 |
| @@ -652,8 +607,8 @@ public class PlayServiceImpl implements IPlayService { | @@ -652,8 +607,8 @@ public class PlayServiceImpl implements IPlayService { | ||
| 652 | 607 | ||
| 653 | @Override | 608 | @Override |
| 654 | public void playBack(String deviceId, String channelId, String startTime, | 609 | public void playBack(String deviceId, String channelId, String startTime, |
| 655 | - String endTime, InviteStreamCallback inviteStreamCallback, | ||
| 656 | - PlayBackCallback callback) { | 610 | + String endTime, InviteStreamCallback inviteStreamCallback, |
| 611 | + PlayBackCallback callback) { | ||
| 657 | Device device = storager.queryVideoDevice(deviceId); | 612 | Device device = storager.queryVideoDevice(deviceId); |
| 658 | if (device == null) { | 613 | if (device == null) { |
| 659 | return; | 614 | return; |
| @@ -666,9 +621,9 @@ public class PlayServiceImpl implements IPlayService { | @@ -666,9 +621,9 @@ public class PlayServiceImpl implements IPlayService { | ||
| 666 | 621 | ||
| 667 | @Override | 622 | @Override |
| 668 | public void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, | 623 | public void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, |
| 669 | - String deviceId, String channelId, String startTime, | ||
| 670 | - String endTime, InviteStreamCallback infoCallBack, | ||
| 671 | - PlayBackCallback playBackCallback) { | 624 | + String deviceId, String channelId, String startTime, |
| 625 | + String endTime, InviteStreamCallback infoCallBack, | ||
| 626 | + PlayBackCallback playBackCallback) { | ||
| 672 | if (mediaServerItem == null || ssrcInfo == null) { | 627 | if (mediaServerItem == null || ssrcInfo == null) { |
| 673 | return; | 628 | return; |
| 674 | } | 629 | } |
| @@ -792,7 +747,6 @@ public class PlayServiceImpl implements IPlayService { | @@ -792,7 +747,6 @@ public class PlayServiceImpl implements IPlayService { | ||
| 792 | } | 747 | } |
| 793 | 748 | ||
| 794 | 749 | ||
| 795 | - | ||
| 796 | @Override | 750 | @Override |
| 797 | public void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback playBackCallback) { | 751 | public void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback playBackCallback) { |
| 798 | Device device = storager.queryVideoDevice(deviceId); | 752 | Device device = storager.queryVideoDevice(deviceId); |
| @@ -977,7 +931,7 @@ public class PlayServiceImpl implements IPlayService { | @@ -977,7 +931,7 @@ public class PlayServiceImpl implements IPlayService { | ||
| 977 | cmder.streamByeCmd(device, ssrcTransaction.getChannelId(), | 931 | cmder.streamByeCmd(device, ssrcTransaction.getChannelId(), |
| 978 | ssrcTransaction.getStream(), null); | 932 | ssrcTransaction.getStream(), null); |
| 979 | } catch (InvalidArgumentException | ParseException | SipException | | 933 | } catch (InvalidArgumentException | ParseException | SipException | |
| 980 | - SsrcTransactionNotFoundException e) { | 934 | + SsrcTransactionNotFoundException e) { |
| 981 | logger.error("[zlm离线]为正在使用此zlm的设备, 发送BYE失败 {}", e.getMessage()); | 935 | logger.error("[zlm离线]为正在使用此zlm的设备, 发送BYE失败 {}", e.getMessage()); |
| 982 | } | 936 | } |
| 983 | } | 937 | } |
| @@ -987,6 +941,7 @@ public class PlayServiceImpl implements IPlayService { | @@ -987,6 +941,7 @@ public class PlayServiceImpl implements IPlayService { | ||
| 987 | 941 | ||
| 988 | @Override | 942 | @Override |
| 989 | public AudioBroadcastResult audioBroadcast(Device device, String channelId) { | 943 | public AudioBroadcastResult audioBroadcast(Device device, String channelId) { |
| 944 | + // TODO 必须多端口模式才支持语音喊话鹤语音对讲 | ||
| 990 | if (device == null || channelId == null) { | 945 | if (device == null || channelId == null) { |
| 991 | return null; | 946 | return null; |
| 992 | } | 947 | } |
| @@ -1005,13 +960,13 @@ public class PlayServiceImpl implements IPlayService { | @@ -1005,13 +960,13 @@ public class PlayServiceImpl implements IPlayService { | ||
| 1005 | AudioBroadcastResult audioBroadcastResult = new AudioBroadcastResult(); | 960 | AudioBroadcastResult audioBroadcastResult = new AudioBroadcastResult(); |
| 1006 | audioBroadcastResult.setApp(app); | 961 | audioBroadcastResult.setApp(app); |
| 1007 | audioBroadcastResult.setStream(stream); | 962 | audioBroadcastResult.setStream(stream); |
| 1008 | - audioBroadcastResult.setStreamInfo(new StreamContent(mediaService.getStreamInfoByAppAndStream(mediaServerItem, app, stream, null, null, null,false))); | 963 | + audioBroadcastResult.setStreamInfo(new StreamContent(mediaService.getStreamInfoByAppAndStream(mediaServerItem, app, stream, null, null, null, false))); |
| 1009 | audioBroadcastResult.setCodec("G.711"); | 964 | audioBroadcastResult.setCodec("G.711"); |
| 1010 | return audioBroadcastResult; | 965 | return audioBroadcastResult; |
| 1011 | } | 966 | } |
| 1012 | 967 | ||
| 1013 | @Override | 968 | @Override |
| 1014 | - public void audioBroadcastCmd(Device device, String channelId, int timeout, AudioBroadcastEvent event) throws InvalidArgumentException, ParseException, SipException { | 969 | + public void audioBroadcastCmd(Device device, String channelId, MediaServerItem mediaServerItem, int timeout, AudioEvent event) throws InvalidArgumentException, ParseException, SipException { |
| 1015 | if (device == null || channelId == null) { | 970 | if (device == null || channelId == null) { |
| 1016 | return; | 971 | return; |
| 1017 | } | 972 | } |
| @@ -1027,8 +982,8 @@ public class PlayServiceImpl implements IPlayService { | @@ -1027,8 +982,8 @@ public class PlayServiceImpl implements IPlayService { | ||
| 1027 | SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(device.getDeviceId(), channelId, null, null); | 982 | SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(device.getDeviceId(), channelId, null, null); |
| 1028 | if (sendRtpItem != null && sendRtpItem.isOnlyAudio()) { | 983 | if (sendRtpItem != null && sendRtpItem.isOnlyAudio()) { |
| 1029 | // 查询流是否存在,不存在则认为是异常状态 | 984 | // 查询流是否存在,不存在则认为是异常状态 |
| 1030 | - MediaServerItem mediaServerItem = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | ||
| 1031 | - Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, sendRtpItem.getApp(), sendRtpItem.getStreamId()); | 985 | + MediaServerItem mediaServer = mediaServerService.getOne(sendRtpItem.getMediaServerId()); |
| 986 | + Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServer, sendRtpItem.getApp(), sendRtpItem.getStream()); | ||
| 1032 | if (streamReady) { | 987 | if (streamReady) { |
| 1033 | logger.warn("语音广播已经开启: {}", channelId); | 988 | logger.warn("语音广播已经开启: {}", channelId); |
| 1034 | event.call("语音广播已经开启"); | 989 | event.call("语音广播已经开启"); |
| @@ -1038,11 +993,23 @@ public class PlayServiceImpl implements IPlayService { | @@ -1038,11 +993,23 @@ public class PlayServiceImpl implements IPlayService { | ||
| 1038 | } | 993 | } |
| 1039 | } | 994 | } |
| 1040 | } | 995 | } |
| 996 | + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(device.getDeviceId(), channelId, null, null); | ||
| 997 | + if (sendRtpItem != null) { | ||
| 998 | + MediaServerItem mediaServer = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | ||
| 999 | + Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServer, "rtp", sendRtpItem.getReceiveStream()); | ||
| 1000 | + if (streamReady) { | ||
| 1001 | + logger.warn("[语音对讲] 进行中: {}", channelId); | ||
| 1002 | + event.call("语音对讲进行中"); | ||
| 1003 | + return; | ||
| 1004 | + } else { | ||
| 1005 | + stopTalk(device, channelId); | ||
| 1006 | + } | ||
| 1007 | + } | ||
| 1041 | 1008 | ||
| 1042 | // 发送通知 | 1009 | // 发送通知 |
| 1043 | cmder.audioBroadcastCmd(device, channelId, eventResultForOk -> { | 1010 | cmder.audioBroadcastCmd(device, channelId, eventResultForOk -> { |
| 1044 | // 发送成功 | 1011 | // 发送成功 |
| 1045 | - AudioBroadcastCatch audioBroadcastCatch = new AudioBroadcastCatch(device.getDeviceId(), channelId, AudioBroadcastCatchStatus.Ready); | 1012 | + AudioBroadcastCatch audioBroadcastCatch = new AudioBroadcastCatch(device.getDeviceId(), channelId, AudioBroadcastCatchStatus.Ready, mediaServerItem); |
| 1046 | audioBroadcastManager.update(audioBroadcastCatch); | 1013 | audioBroadcastManager.update(audioBroadcastCatch); |
| 1047 | }, eventResultForError -> { | 1014 | }, eventResultForError -> { |
| 1048 | // 发送失败 | 1015 | // 发送失败 |
| @@ -1053,19 +1020,18 @@ public class PlayServiceImpl implements IPlayService { | @@ -1053,19 +1020,18 @@ public class PlayServiceImpl implements IPlayService { | ||
| 1053 | } | 1020 | } |
| 1054 | 1021 | ||
| 1055 | 1022 | ||
| 1056 | - | ||
| 1057 | @Override | 1023 | @Override |
| 1058 | public void stopAudioBroadcast(String deviceId, String channelId) { | 1024 | public void stopAudioBroadcast(String deviceId, String channelId) { |
| 1059 | List<AudioBroadcastCatch> audioBroadcastCatchList = new ArrayList<>(); | 1025 | List<AudioBroadcastCatch> audioBroadcastCatchList = new ArrayList<>(); |
| 1060 | if (channelId == null) { | 1026 | if (channelId == null) { |
| 1061 | audioBroadcastCatchList.addAll(audioBroadcastManager.get(deviceId)); | 1027 | audioBroadcastCatchList.addAll(audioBroadcastManager.get(deviceId)); |
| 1062 | - }else { | 1028 | + } else { |
| 1063 | audioBroadcastCatchList.add(audioBroadcastManager.get(deviceId, channelId)); | 1029 | audioBroadcastCatchList.add(audioBroadcastManager.get(deviceId, channelId)); |
| 1064 | } | 1030 | } |
| 1065 | if (audioBroadcastCatchList.size() > 0) { | 1031 | if (audioBroadcastCatchList.size() > 0) { |
| 1066 | for (AudioBroadcastCatch audioBroadcastCatch : audioBroadcastCatchList) { | 1032 | for (AudioBroadcastCatch audioBroadcastCatch : audioBroadcastCatchList) { |
| 1067 | Device device = deviceService.getDevice(deviceId); | 1033 | Device device = deviceService.getDevice(deviceId); |
| 1068 | - if (device == null || audioBroadcastCatch == null ) { | 1034 | + if (device == null || audioBroadcastCatch == null) { |
| 1069 | return; | 1035 | return; |
| 1070 | } | 1036 | } |
| 1071 | SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(deviceId, audioBroadcastCatch.getChannelId(), null, null); | 1037 | SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(deviceId, audioBroadcastCatch.getChannelId(), null, null); |
| @@ -1075,7 +1041,7 @@ public class PlayServiceImpl implements IPlayService { | @@ -1075,7 +1041,7 @@ public class PlayServiceImpl implements IPlayService { | ||
| 1075 | Map<String, Object> param = new HashMap<>(); | 1041 | Map<String, Object> param = new HashMap<>(); |
| 1076 | param.put("vhost", "__defaultVhost__"); | 1042 | param.put("vhost", "__defaultVhost__"); |
| 1077 | param.put("app", sendRtpItem.getApp()); | 1043 | param.put("app", sendRtpItem.getApp()); |
| 1078 | - param.put("stream", sendRtpItem.getStreamId()); | 1044 | + param.put("stream", sendRtpItem.getStream()); |
| 1079 | zlmresTfulUtils.stopSendRtp(mediaInfo, param); | 1045 | zlmresTfulUtils.stopSendRtp(mediaInfo, param); |
| 1080 | try { | 1046 | try { |
| 1081 | cmder.streamByeCmd(device, sendRtpItem.getChannelId(), audioBroadcastCatch.getSipTransactionInfo(), null); | 1047 | cmder.streamByeCmd(device, sendRtpItem.getChannelId(), audioBroadcastCatch.getSipTransactionInfo(), null); |
| @@ -1199,12 +1165,12 @@ public class PlayServiceImpl implements IPlayService { | @@ -1199,12 +1165,12 @@ public class PlayServiceImpl implements IPlayService { | ||
| 1199 | 1165 | ||
| 1200 | String is_Udp = sendRtpItem.isTcp() ? "0" : "1"; | 1166 | String is_Udp = sendRtpItem.isTcp() ? "0" : "1"; |
| 1201 | MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | 1167 | MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); |
| 1202 | - logger.info("收到ACK,rtp/{}开始向上级推流, 目标={}:{},SSRC={}, RTCP={}", sendRtpItem.getStreamId(), | 1168 | + logger.info("收到ACK,rtp/{}开始向上级推流, 目标={}:{},SSRC={}, RTCP={}", sendRtpItem.getStream(), |
| 1203 | sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isRtcp()); | 1169 | sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isRtcp()); |
| 1204 | Map<String, Object> param = new HashMap<>(12); | 1170 | Map<String, Object> param = new HashMap<>(12); |
| 1205 | - param.put("vhost","__defaultVhost__"); | ||
| 1206 | - param.put("app",sendRtpItem.getApp()); | ||
| 1207 | - param.put("stream",sendRtpItem.getStreamId()); | 1171 | + param.put("vhost", "__defaultVhost__"); |
| 1172 | + param.put("app", sendRtpItem.getApp()); | ||
| 1173 | + param.put("stream", sendRtpItem.getStream()); | ||
| 1208 | param.put("ssrc", sendRtpItem.getSsrc()); | 1174 | param.put("ssrc", sendRtpItem.getSsrc()); |
| 1209 | param.put("src_port", sendRtpItem.getLocalPort()); | 1175 | param.put("src_port", sendRtpItem.getLocalPort()); |
| 1210 | param.put("pt", sendRtpItem.getPt()); | 1176 | param.put("pt", sendRtpItem.getPt()); |
| @@ -1213,12 +1179,12 @@ public class PlayServiceImpl implements IPlayService { | @@ -1213,12 +1179,12 @@ public class PlayServiceImpl implements IPlayService { | ||
| 1213 | param.put("is_udp", is_Udp); | 1179 | param.put("is_udp", is_Udp); |
| 1214 | if (!sendRtpItem.isTcp()) { | 1180 | if (!sendRtpItem.isTcp()) { |
| 1215 | // udp模式下开启rtcp保活 | 1181 | // udp模式下开启rtcp保活 |
| 1216 | - param.put("udp_rtcp_timeout", sendRtpItem.isRtcp()? "1":"0"); | 1182 | + param.put("udp_rtcp_timeout", sendRtpItem.isRtcp() ? "1" : "0"); |
| 1217 | } | 1183 | } |
| 1218 | 1184 | ||
| 1219 | if (mediaInfo == null) { | 1185 | if (mediaInfo == null) { |
| 1220 | RequestPushStreamMsg requestPushStreamMsg = RequestPushStreamMsg.getInstance( | 1186 | RequestPushStreamMsg requestPushStreamMsg = RequestPushStreamMsg.getInstance( |
| 1221 | - sendRtpItem.getMediaServerId(), sendRtpItem.getApp(), sendRtpItem.getStreamId(), | 1187 | + sendRtpItem.getMediaServerId(), sendRtpItem.getApp(), sendRtpItem.getStream(), |
| 1222 | sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isTcp(), | 1188 | sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isTcp(), |
| 1223 | sendRtpItem.getLocalPort(), sendRtpItem.getPt(), sendRtpItem.isUsePs(), sendRtpItem.isOnlyAudio()); | 1189 | sendRtpItem.getLocalPort(), sendRtpItem.getPt(), sendRtpItem.isUsePs(), sendRtpItem.isOnlyAudio()); |
| 1224 | redisGbPlayMsgListener.sendMsgForStartSendRtpStream(sendRtpItem.getServerId(), requestPushStreamMsg, json -> { | 1190 | redisGbPlayMsgListener.sendMsgForStartSendRtpStream(sendRtpItem.getServerId(), requestPushStreamMsg, json -> { |
| @@ -1233,16 +1199,16 @@ public class PlayServiceImpl implements IPlayService { | @@ -1233,16 +1199,16 @@ public class PlayServiceImpl implements IPlayService { | ||
| 1233 | if (zlmrtpServerFactory.releasePort(mediaInfo, sendRtpItem.getSsrc())) { | 1199 | if (zlmrtpServerFactory.releasePort(mediaInfo, sendRtpItem.getSsrc())) { |
| 1234 | if (sendRtpItem.isTcpActive()) { | 1200 | if (sendRtpItem.isTcpActive()) { |
| 1235 | startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpPassive(mediaInfo, param); | 1201 | startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpPassive(mediaInfo, param); |
| 1236 | - }else { | 1202 | + } else { |
| 1237 | param.put("dst_url", sendRtpItem.getIp()); | 1203 | param.put("dst_url", sendRtpItem.getIp()); |
| 1238 | param.put("dst_port", sendRtpItem.getPort()); | 1204 | param.put("dst_port", sendRtpItem.getPort()); |
| 1239 | startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); | 1205 | startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); |
| 1240 | } | 1206 | } |
| 1241 | } | 1207 | } |
| 1242 | - }else { | 1208 | + } else { |
| 1243 | if (sendRtpItem.isTcpActive()) { | 1209 | if (sendRtpItem.isTcpActive()) { |
| 1244 | startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpPassive(mediaInfo, param); | 1210 | startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpPassive(mediaInfo, param); |
| 1245 | - }else { | 1211 | + } else { |
| 1246 | param.put("dst_url", sendRtpItem.getIp()); | 1212 | param.put("dst_url", sendRtpItem.getIp()); |
| 1247 | param.put("dst_port", sendRtpItem.getPort()); | 1213 | param.put("dst_port", sendRtpItem.getPort()); |
| 1248 | startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); | 1214 | startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); |
| @@ -1260,10 +1226,10 @@ public class PlayServiceImpl implements IPlayService { | @@ -1260,10 +1226,10 @@ public class PlayServiceImpl implements IPlayService { | ||
| 1260 | if (jsonObject == null) { | 1226 | if (jsonObject == null) { |
| 1261 | logger.error("RTP推流失败: 请检查ZLM服务"); | 1227 | logger.error("RTP推流失败: 请检查ZLM服务"); |
| 1262 | } else if (jsonObject.getInteger("code") == 0) { | 1228 | } else if (jsonObject.getInteger("code") == 0) { |
| 1263 | - logger.info("调用ZLM推流接口, 结果: {}", jsonObject); | ||
| 1264 | - logger.info("RTP推流成功[ {}/{} ],{}->{}:{}, " ,param.get("app"), param.get("stream"), jsonObject.getString("local_port"), param.get("dst_url"), param.get("dst_port")); | 1229 | + logger.info("调用ZLM推流接口, 结果: {}", jsonObject); |
| 1230 | + logger.info("RTP推流成功[ {}/{} ],{}->{}:{}, ", param.get("app"), param.get("stream"), jsonObject.getString("local_port"), param.get("dst_url"), param.get("dst_port")); | ||
| 1265 | } else { | 1231 | } else { |
| 1266 | - logger.error("RTP推流失败: {}, 参数:{}",jsonObject.getString("msg"), JSON.toJSONString(param)); | 1232 | + logger.error("RTP推流失败: {}, 参数:{}", jsonObject.getString("msg"), JSON.toJSONString(param)); |
| 1267 | if (sendRtpItem.isOnlyAudio()) { | 1233 | if (sendRtpItem.isOnlyAudio()) { |
| 1268 | Device device = deviceService.getDevice(sendRtpItem.getDeviceId()); | 1234 | Device device = deviceService.getDevice(sendRtpItem.getDeviceId()); |
| 1269 | AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); | 1235 | AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); |
| @@ -1275,7 +1241,7 @@ public class PlayServiceImpl implements IPlayService { | @@ -1275,7 +1241,7 @@ public class PlayServiceImpl implements IPlayService { | ||
| 1275 | logger.error("[命令发送失败] 停止语音对讲: {}", e.getMessage()); | 1241 | logger.error("[命令发送失败] 停止语音对讲: {}", e.getMessage()); |
| 1276 | } | 1242 | } |
| 1277 | } | 1243 | } |
| 1278 | - }else { | 1244 | + } else { |
| 1279 | // 向上级平台 | 1245 | // 向上级平台 |
| 1280 | try { | 1246 | try { |
| 1281 | commanderForPlatform.streamByeCmd(parentPlatform, callIdHeader.getCallId()); | 1247 | commanderForPlatform.streamByeCmd(parentPlatform, callIdHeader.getCallId()); |
| @@ -1285,4 +1251,105 @@ public class PlayServiceImpl implements IPlayService { | @@ -1285,4 +1251,105 @@ public class PlayServiceImpl implements IPlayService { | ||
| 1285 | } | 1251 | } |
| 1286 | } | 1252 | } |
| 1287 | } | 1253 | } |
| 1254 | + | ||
| 1255 | + @Override | ||
| 1256 | + public void talkCmd(Device device, String channelId, MediaServerItem mediaServerItem, String stream, AudioEvent event) { | ||
| 1257 | + if (device == null || channelId == null) { | ||
| 1258 | + return; | ||
| 1259 | + } | ||
| 1260 | + // TODO 必须多端口模式才支持语音喊话鹤语音对讲 | ||
| 1261 | + logger.info("[语音对讲] device: {}, channel: {}", device.getDeviceId(), channelId); | ||
| 1262 | + DeviceChannel deviceChannel = storager.queryChannel(device.getDeviceId(), channelId); | ||
| 1263 | + if (deviceChannel == null) { | ||
| 1264 | + logger.warn("开启语音对讲的时候未找到通道: {}", channelId); | ||
| 1265 | + event.call("开启语音对讲的时候未找到通道"); | ||
| 1266 | + return; | ||
| 1267 | + } | ||
| 1268 | + // 查询通道使用状态 | ||
| 1269 | + if (audioBroadcastManager.exit(device.getDeviceId(), channelId)) { | ||
| 1270 | + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(device.getDeviceId(), channelId, null, null); | ||
| 1271 | + if (sendRtpItem != null && sendRtpItem.isOnlyAudio()) { | ||
| 1272 | + // 查询流是否存在,不存在则认为是异常状态 | ||
| 1273 | + MediaServerItem mediaServer = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | ||
| 1274 | + Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServer, sendRtpItem.getApp(), sendRtpItem.getStream()); | ||
| 1275 | + if (streamReady) { | ||
| 1276 | + logger.warn("[语音对讲] 正在语音广播,无法开启语音通话: {}", channelId); | ||
| 1277 | + event.call("正在语音广播"); | ||
| 1278 | + return; | ||
| 1279 | + } else { | ||
| 1280 | + stopAudioBroadcast(device.getDeviceId(), channelId); | ||
| 1281 | + } | ||
| 1282 | + } | ||
| 1283 | + } | ||
| 1284 | + | ||
| 1285 | + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(device.getDeviceId(), channelId, stream, null); | ||
| 1286 | + if (sendRtpItem != null) { | ||
| 1287 | + MediaServerItem mediaServer = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | ||
| 1288 | + Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServer, "rtp", sendRtpItem.getReceiveStream()); | ||
| 1289 | + if (streamReady) { | ||
| 1290 | + logger.warn("[语音对讲] 进行中: {}", channelId); | ||
| 1291 | + event.call("语音对讲进行中"); | ||
| 1292 | + return; | ||
| 1293 | + } else { | ||
| 1294 | + stopTalk(device, channelId); | ||
| 1295 | + } | ||
| 1296 | + } | ||
| 1297 | + | ||
| 1298 | + talk(mediaServerItem, device, channelId, stream, (MediaServerItem mediaServerItem1, JSONObject response) -> { | ||
| 1299 | + logger.info("[语音对讲] 收到设备发来的流"); | ||
| 1300 | + }, eventResult -> { | ||
| 1301 | + logger.warn("[语音对讲] 失败,{}/{}, 错误码 {} {}", device.getDeviceId(), channelId, eventResult.statusCode, eventResult.msg); | ||
| 1302 | + event.call("失败,错误码 " + eventResult.statusCode + ", " + eventResult.msg); | ||
| 1303 | + }, () -> { | ||
| 1304 | + logger.warn("[语音对讲] 失败,{}/{} 超时", device.getDeviceId(), channelId); | ||
| 1305 | + event.call("失败,超时 "); | ||
| 1306 | + stopTalk(device, channelId); | ||
| 1307 | + }, errorMsg -> { | ||
| 1308 | + logger.warn("[语音对讲] 失败,{}/{} {}", device.getDeviceId(), channelId, errorMsg); | ||
| 1309 | + event.call(errorMsg); | ||
| 1310 | + stopTalk(device, channelId); | ||
| 1311 | + }); | ||
| 1312 | + } | ||
| 1313 | + | ||
| 1314 | + private void stopTalk(Device device, String channelId) { | ||
| 1315 | + stopTalk(device, channelId, null); | ||
| 1316 | + } | ||
| 1317 | + | ||
| 1318 | + @Override | ||
| 1319 | + public void stopTalk(Device device, String channelId, Boolean streamIsReady) { | ||
| 1320 | + logger.info("[语音对讲] 停止, {}/{}", device.getDeviceId(), channelId); | ||
| 1321 | + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(device.getDeviceId(), channelId, null, null); | ||
| 1322 | + if (sendRtpItem == null) { | ||
| 1323 | + logger.info("[语音对讲] 停止失败, 未找到发送信息,可能已经停止"); | ||
| 1324 | + return; | ||
| 1325 | + } | ||
| 1326 | + // 停止向设备推流 | ||
| 1327 | + String mediaServerId = sendRtpItem.getMediaServerId(); | ||
| 1328 | + if (mediaServerId == null) { | ||
| 1329 | + return; | ||
| 1330 | + } | ||
| 1331 | + | ||
| 1332 | + MediaServerItem mediaServer = mediaServerService.getOne(mediaServerId); | ||
| 1333 | + | ||
| 1334 | + if (streamIsReady == null || streamIsReady) { | ||
| 1335 | + Map<String, Object> param = new HashMap<>(); | ||
| 1336 | + param.put("vhost", "__defaultVhost__"); | ||
| 1337 | + param.put("app", sendRtpItem.getApp()); | ||
| 1338 | + param.put("stream", sendRtpItem.getStream()); | ||
| 1339 | + param.put("ssrc", sendRtpItem.getSsrc()); | ||
| 1340 | + zlmrtpServerFactory.stopSendRtpStream(mediaServer, param); | ||
| 1341 | + } | ||
| 1342 | + | ||
| 1343 | + mediaServer.getSsrcConfig().releaseSsrc(sendRtpItem.getSsrc()); | ||
| 1344 | + | ||
| 1345 | + SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, null, sendRtpItem.getStream()); | ||
| 1346 | + if (ssrcTransaction != null) { | ||
| 1347 | + try { | ||
| 1348 | + cmder.streamByeCmd(device, channelId, sendRtpItem.getStream(), null); | ||
| 1349 | + } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) { | ||
| 1350 | + logger.info("[语音对讲] 停止消息发送失败,可能已经停止"); | ||
| 1351 | + } | ||
| 1352 | + } | ||
| 1353 | + redisCatchStorage.deleteSendRTPServer(device.getDeviceId(), channelId,null, null); | ||
| 1354 | + } | ||
| 1288 | } | 1355 | } |
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
| @@ -378,7 +378,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | @@ -378,7 +378,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | ||
| 378 | + sendRtpItem.getMediaServerId() + "_" | 378 | + sendRtpItem.getMediaServerId() + "_" |
| 379 | + sendRtpItem.getPlatformId() + "_" | 379 | + sendRtpItem.getPlatformId() + "_" |
| 380 | + sendRtpItem.getChannelId() + "_" | 380 | + sendRtpItem.getChannelId() + "_" |
| 381 | - + sendRtpItem.getStreamId() + "_" | 381 | + + sendRtpItem.getStream() + "_" |
| 382 | + sendRtpItem.getCallId(); | 382 | + sendRtpItem.getCallId(); |
| 383 | RedisUtil.set(key, sendRtpItem); | 383 | RedisUtil.set(key, sendRtpItem); |
| 384 | } | 384 | } |
src/main/java/com/genersoft/iot/vmp/vmanager/bean/StreamContent.java
| 1 | package com.genersoft.iot.vmp.vmanager.bean; | 1 | package com.genersoft.iot.vmp.vmanager.bean; |
| 2 | 2 | ||
| 3 | import com.genersoft.iot.vmp.common.StreamInfo; | 3 | import com.genersoft.iot.vmp.common.StreamInfo; |
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | 5 | ||
| 6 | +@Schema(description = "流信息") | ||
| 5 | public class StreamContent { | 7 | public class StreamContent { |
| 6 | 8 | ||
| 9 | + @Schema(description = "应用名") | ||
| 7 | private String app; | 10 | private String app; |
| 11 | + | ||
| 12 | + @Schema(description = "流ID") | ||
| 8 | private String stream; | 13 | private String stream; |
| 9 | 14 | ||
| 15 | + @Schema(description = "IP") | ||
| 10 | private String ip; | 16 | private String ip; |
| 11 | 17 | ||
| 18 | + @Schema(description = "HTTP-FLV流地址") | ||
| 12 | private String flv; | 19 | private String flv; |
| 13 | 20 | ||
| 21 | + @Schema(description = "HTTPS-FLV流地址") | ||
| 14 | private String https_flv; | 22 | private String https_flv; |
| 23 | + | ||
| 24 | + @Schema(description = "Websocket-FLV流地址") | ||
| 15 | private String ws_flv; | 25 | private String ws_flv; |
| 26 | + | ||
| 27 | + @Schema(description = "Websockets-FLV流地址") | ||
| 16 | private String wss_flv; | 28 | private String wss_flv; |
| 29 | + | ||
| 30 | + @Schema(description = "HTTP-FMP4流地址") | ||
| 17 | private String fmp4; | 31 | private String fmp4; |
| 32 | + | ||
| 33 | + @Schema(description = "HTTPS-FMP4流地址") | ||
| 18 | private String https_fmp4; | 34 | private String https_fmp4; |
| 35 | + | ||
| 36 | + @Schema(description = "Websocket-FMP4流地址") | ||
| 19 | private String ws_fmp4; | 37 | private String ws_fmp4; |
| 38 | + | ||
| 39 | + @Schema(description = "Websockets-FMP4流地址") | ||
| 20 | private String wss_fmp4; | 40 | private String wss_fmp4; |
| 41 | + | ||
| 42 | + @Schema(description = "HLS流地址") | ||
| 21 | private String hls; | 43 | private String hls; |
| 44 | + | ||
| 45 | + @Schema(description = "HTTPS-HLS流地址") | ||
| 22 | private String https_hls; | 46 | private String https_hls; |
| 47 | + | ||
| 48 | + @Schema(description = "Websocket-HLS流地址") | ||
| 23 | private String ws_hls; | 49 | private String ws_hls; |
| 50 | + | ||
| 51 | + @Schema(description = "Websockets-HLS流地址") | ||
| 24 | private String wss_hls; | 52 | private String wss_hls; |
| 53 | + | ||
| 54 | + @Schema(description = "HTTP-TS流地址") | ||
| 25 | private String ts; | 55 | private String ts; |
| 56 | + | ||
| 57 | + @Schema(description = "HTTPS-TS流地址") | ||
| 26 | private String https_ts; | 58 | private String https_ts; |
| 59 | + | ||
| 60 | + @Schema(description = "Websocket-TS流地址") | ||
| 27 | private String ws_ts; | 61 | private String ws_ts; |
| 62 | + | ||
| 63 | + @Schema(description = "Websockets-TS流地址") | ||
| 28 | private String wss_ts; | 64 | private String wss_ts; |
| 65 | + | ||
| 66 | + @Schema(description = "RTMP流地址") | ||
| 29 | private String rtmp; | 67 | private String rtmp; |
| 68 | + | ||
| 69 | + @Schema(description = "RTMPS流地址") | ||
| 30 | private String rtmps; | 70 | private String rtmps; |
| 71 | + | ||
| 72 | + @Schema(description = "RTSP流地址") | ||
| 31 | private String rtsp; | 73 | private String rtsp; |
| 74 | + | ||
| 75 | + @Schema(description = "RTSPS流地址") | ||
| 32 | private String rtsps; | 76 | private String rtsps; |
| 77 | + | ||
| 78 | + @Schema(description = "RTC流地址") | ||
| 33 | private String rtc; | 79 | private String rtc; |
| 34 | 80 | ||
| 81 | + @Schema(description = "RTCS流地址") | ||
| 35 | private String rtcs; | 82 | private String rtcs; |
| 83 | + | ||
| 84 | + @Schema(description = "流媒体ID") | ||
| 36 | private String mediaServerId; | 85 | private String mediaServerId; |
| 86 | + | ||
| 87 | + @Schema(description = "流编码信息") | ||
| 37 | private Object tracks; | 88 | private Object tracks; |
| 38 | 89 | ||
| 90 | + @Schema(description = "开始时间") | ||
| 39 | private String startTime; | 91 | private String startTime; |
| 40 | 92 | ||
| 93 | + @Schema(description = "结束时间") | ||
| 41 | private String endTime; | 94 | private String endTime; |
| 42 | 95 | ||
| 43 | private double progress; | 96 | private double progress; |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
| @@ -19,11 +19,7 @@ import com.genersoft.iot.vmp.service.IMediaService; | @@ -19,11 +19,7 @@ import com.genersoft.iot.vmp.service.IMediaService; | ||
| 19 | import com.genersoft.iot.vmp.service.IPlayService; | 19 | import com.genersoft.iot.vmp.service.IPlayService; |
| 20 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | 20 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 21 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | 21 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 22 | -import com.genersoft.iot.vmp.vmanager.bean.DeferredResultEx; | ||
| 23 | -import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; | ||
| 24 | -import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; | ||
| 25 | -import com.genersoft.iot.vmp.vmanager.bean.StreamContent; | ||
| 26 | -import com.genersoft.iot.vmp.vmanager.bean.WVPResult; | 22 | +import com.genersoft.iot.vmp.vmanager.bean.*; |
| 27 | import io.swagger.v3.oas.annotations.Operation; | 23 | import io.swagger.v3.oas.annotations.Operation; |
| 28 | import io.swagger.v3.oas.annotations.Parameter; | 24 | import io.swagger.v3.oas.annotations.Parameter; |
| 29 | import io.swagger.v3.oas.annotations.tags.Tag; | 25 | import io.swagger.v3.oas.annotations.tags.Tag; |
| @@ -269,14 +265,6 @@ public class PlayController { | @@ -269,14 +265,6 @@ public class PlayController { | ||
| 269 | 265 | ||
| 270 | } | 266 | } |
| 271 | 267 | ||
| 272 | - @GetMapping("/1111") | ||
| 273 | - public void broadcastApi1() { | ||
| 274 | - MediaServerItem defaultMediaServer = mediaServerService.getMediaServerForMinimumLoad(null); | ||
| 275 | - Device device = storager.queryVideoDevice("34020000001320090001"); | ||
| 276 | - playService.talk(defaultMediaServer, device, "34020000001370000001", null, null, null); | ||
| 277 | - | ||
| 278 | - } | ||
| 279 | - | ||
| 280 | 268 | ||
| 281 | @Operation(summary = "停止语音广播") | 269 | @Operation(summary = "停止语音广播") |
| 282 | @Parameter(name = "deviceId", description = "设备Id", required = true) | 270 | @Parameter(name = "deviceId", description = "设备Id", required = true) |
| @@ -289,7 +277,7 @@ public class PlayController { | @@ -289,7 +277,7 @@ public class PlayController { | ||
| 289 | } | 277 | } |
| 290 | // try { | 278 | // try { |
| 291 | // playService.stopAudioBroadcast(deviceId, channelId); | 279 | // playService.stopAudioBroadcast(deviceId, channelId); |
| 292 | -// } catch (InvalidArgumentException | ParseException | SsrcTransactionNotFoundException | SipException e) { | 280 | +// } catch (InvalidArgumentException | ParseException | SipException e) { |
| 293 | // logger.error("[命令发送失败] 停止语音: {}", e.getMessage()); | 281 | // logger.error("[命令发送失败] 停止语音: {}", e.getMessage()); |
| 294 | // throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); | 282 | // throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); |
| 295 | // } | 283 | // } |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/bean/AudioBroadcastEvent.java renamed to src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/bean/AudioEvent.java
| @@ -4,6 +4,6 @@ package com.genersoft.iot.vmp.vmanager.gb28181.play.bean; | @@ -4,6 +4,6 @@ package com.genersoft.iot.vmp.vmanager.gb28181.play.bean; | ||
| 4 | /** | 4 | /** |
| 5 | * @author lin | 5 | * @author lin |
| 6 | */ | 6 | */ |
| 7 | -public interface AudioBroadcastEvent { | 7 | +public interface AudioEvent { |
| 8 | void call(String msg); | 8 | void call(String msg); |
| 9 | } | 9 | } |
src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java
| @@ -185,7 +185,7 @@ public class ApiStreamController { | @@ -185,7 +185,7 @@ public class ApiStreamController { | ||
| 185 | } | 185 | } |
| 186 | try { | 186 | try { |
| 187 | cmder.streamByeCmd(device, code, streamInfo.getStream(), null); | 187 | cmder.streamByeCmd(device, code, streamInfo.getStream(), null); |
| 188 | - } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) { | 188 | + } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) { |
| 189 | JSONObject result = new JSONObject(); | 189 | JSONObject result = new JSONObject(); |
| 190 | result.put("error","发送BYE失败:" + e.getMessage()); | 190 | result.put("error","发送BYE失败:" + e.getMessage()); |
| 191 | return result; | 191 | return result; |