From 8b90fade9eb3a62b428f23f2306cb1911c98d355 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: 星期二, 02 四月 2024 00:05:09 +0800 Subject: [PATCH] 支持使用abl接收国标流 --- src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java | 410 +++++++++++++++++++++++++++++++++++++++++++--------------- 1 files changed, 301 insertions(+), 109 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java index a4f3b5e..88fffba 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java @@ -2,22 +2,30 @@ import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; +import com.genersoft.iot.vmp.common.InviteSessionType; import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.conf.DynamicTask; +import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.gb28181.bean.*; +import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; +import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; import com.genersoft.iot.vmp.gb28181.utils.SipUtils; +import com.genersoft.iot.vmp.media.bean.MediaServer; +import com.genersoft.iot.vmp.media.event.hook.Hook; +import com.genersoft.iot.vmp.media.event.hook.HookType; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager; import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; -import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; +import com.genersoft.iot.vmp.media.event.hook.HookSubscribe; import com.genersoft.iot.vmp.media.zlm.dto.*; -import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; import com.genersoft.iot.vmp.service.*; import com.genersoft.iot.vmp.service.bean.ErrorCallback; import com.genersoft.iot.vmp.service.bean.InviteErrorCode; @@ -30,8 +38,10 @@ import com.genersoft.iot.vmp.utils.DateUtil; import gov.nist.javax.sdp.TimeDescriptionImpl; import gov.nist.javax.sdp.fields.TimeField; +import gov.nist.javax.sdp.fields.URIField; import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPResponse; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; @@ -63,13 +73,14 @@ private final String method = "INVITE"; @Autowired - private SIPCommanderFroPlatform cmderFroPlatform; + private ISIPCommanderForPlatform cmderFroPlatform; @Autowired private IVideoManagerStorage storager; @Autowired private IStreamPushService streamPushService; + @Autowired private IStreamProxyService streamProxyService; @@ -95,13 +106,16 @@ private SIPSender sipSender; @Autowired + private AudioBroadcastManager audioBroadcastManager; + + @Autowired private ZLMServerFactory zlmServerFactory; @Autowired private IMediaServerService mediaServerService; @Autowired - private ZlmHttpHookSubscribe zlmHttpHookSubscribe; + private HookSubscribe hookSubscribe; @Autowired private SIPProcessorObserver sipProcessorObserver; @@ -112,9 +126,15 @@ @Autowired private ZLMMediaListManager mediaListManager; + @Autowired + private SipConfig config; + @Autowired private RedisGbPlayMsgListener redisGbPlayMsgListener; + + @Autowired + private VideoStreamSessionManager streamSession; @Override @@ -133,11 +153,24 @@ // Invite Request娑堟伅瀹炵幇锛屾娑堟伅涓�鑸负绾ц仈娑堟伅锛屼笂绾х粰涓嬬骇鍙戦�佽姹傝棰戞寚浠� try { SIPRequest request = (SIPRequest)evt.getRequest(); - String channelId = SipUtils.getChannelIdFromRequest(request); + String channelIdFromSub = SipUtils.getChannelIdFromRequest(request); + + // 瑙f瀽sdp娑堟伅, 浣跨敤jainsip 鑷甫鐨剆dp瑙f瀽鏂瑰紡 + String contentString = new String(request.getRawContent()); + Gb28181Sdp gb28181Sdp = SipUtils.parseSDP(contentString); + SessionDescription sdp = gb28181Sdp.getBaseSdb(); + String sessionName = sdp.getSessionName().getValue(); + String channelIdFromSdp = null; + if(StringUtils.equalsIgnoreCase("Playback", sessionName)){ + URIField uriField = (URIField)sdp.getURI(); + channelIdFromSdp = uriField.getURI().split(":")[0]; + } + final String channelId = StringUtils.isNotBlank(channelIdFromSdp) ? channelIdFromSdp : channelIdFromSub; + String requesterId = SipUtils.getUserIdFromFromHeader(request); CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME); if (requesterId == null || channelId == null) { - logger.info("鏃犳硶浠嶧romHeader鐨凙ddress涓幏鍙栧埌骞冲彴id锛岃繑鍥�400"); + logger.info("鏃犳硶浠庤姹備腑鑾峰彇鍒板钩鍙癷d锛岃繑鍥�400"); // 鍙傛暟涓嶅叏锛� 鍙�400锛岃姹傞敊璇� try { responseAck(request, Response.BAD_REQUEST); @@ -147,11 +180,13 @@ return; } + logger.info("[INVITE] requesterId: {}, callId: {}, 鏉ヨ嚜锛歿}锛歿}", + requesterId, callIdHeader.getCallId(), request.getRemoteAddress(), request.getRemotePort()); // 鏌ヨ璇锋眰鏄惁鏉ヨ嚜涓婄骇骞冲彴\璁惧 ParentPlatform platform = storager.queryParentPlatByServerGBId(requesterId); if (platform == null) { - inviteFromDeviceHandle(request, requesterId); + inviteFromDeviceHandle(request, requesterId, channelId); } else { // 鏌ヨ骞冲彴涓嬫槸鍚︽湁璇ラ�氶亾 @@ -159,9 +194,9 @@ GbStream gbStream = storager.queryStreamInParentPlatform(requesterId, channelId); PlatformCatalog catalog = storager.getCatalog(requesterId, channelId); - MediaServerItem mediaServerItem = null; + MediaServer mediaServerItem = null; StreamPushItem streamPushItem = null; - StreamProxyItem proxyByAppAndStream =null; + StreamProxyItem proxyByAppAndStream = null; // 涓嶆槸閫氶亾鍙兘鏄洿鎾祦 if (channel != null && gbStream == null) { // 閫氶亾瀛樺湪锛屽彂100锛孴RYING @@ -204,7 +239,7 @@ } return; } - }else if("proxy".equals(gbStream.getStreamType())){ + } else if ("proxy".equals(gbStream.getStreamType())) { proxyByAppAndStream = streamProxyService.getStreamProxyByAppAndStream(gbStream.getApp(), gbStream.getStream()); if (proxyByAppAndStream == null) { logger.info("[ app={}, stream={} ]鎵句笉鍒皕lm {}锛岃繑鍥�410", gbStream.getApp(), gbStream.getStream(), mediaServerId); @@ -240,12 +275,6 @@ } return; } - // 瑙f瀽sdp娑堟伅, 浣跨敤jainsip 鑷甫鐨剆dp瑙f瀽鏂瑰紡 - String contentString = new String(request.getRawContent()); - - Gb28181Sdp gb28181Sdp = SipUtils.parseSDP(contentString); - SessionDescription sdp = gb28181Sdp.getBaseSdb(); - String sessionName = sdp.getSessionName().getValue(); Long startTime = null; Long stopTime = null; @@ -342,10 +371,10 @@ if (mediaTransmissionTCP) { if (tcpActive) { streamTypeStr = "TCP-ACTIVE"; - }else { + } else { streamTypeStr = "TCP-PASSIVE"; } - }else { + } else { streamTypeStr = "UDP"; } logger.info("[涓婄骇Invite] {}, 骞冲彴锛歿}锛� 閫氶亾锛歿}, 鏀舵祦鍦板潃锛歿}:{}锛屾敹娴佹柟寮忥細{}, ssrc锛歿}", sessionName, username, channelId, addressStr, port, streamTypeStr, ssrc); @@ -371,7 +400,7 @@ Long finalStopTime = stopTime; ErrorCallback<Object> hookEvent = (code, msg, data) -> { StreamInfo streamInfo = (StreamInfo)data; - MediaServerItem mediaServerItemInUSe = mediaServerService.getOne(streamInfo.getMediaServerId()); + MediaServer mediaServerItemInUSe = mediaServerService.getOne(streamInfo.getMediaServerId()); logger.info("[涓婄骇Invite]涓嬬骇宸茬粡寮�濮嬫帹娴併�� 鍥炲200OK(SDP)锛� {}/{}", streamInfo.getApp(), streamInfo.getStream()); // * 0 绛夊緟璁惧鎺ㄦ祦涓婃潵 // * 1 涓嬬骇宸茬粡鎺ㄦ祦锛岀瓑寰呬笂绾у钩鍙板洖澶峚ck @@ -394,7 +423,16 @@ // 闈炰弗鏍兼ā寮忕鍙d笉缁熶竴, 澧炲姞鍏煎鎬э紝淇敼涓轰竴涓笉涓�0鐨勭鍙� localPort = new Random().nextInt(65535) + 1; } - content.append("m=video " + localPort + " RTP/AVP 96\r\n"); + if (sendRtpItem.isTcp()) { + content.append("m=video " + localPort + " TCP/RTP/AVP 96\r\n"); + if (!sendRtpItem.isTcpActive()) { + content.append("a=setup:active\r\n"); + } else { + content.append("a=setup:passive\r\n"); + } + }else { + content.append("m=video " + localPort + " RTP/AVP 96\r\n"); + } content.append("a=sendonly\r\n"); content.append("a=rtpmap:96 PS/90000\r\n"); content.append("y=" + sendRtpItem.getSsrc() + "\r\n"); @@ -416,11 +454,11 @@ responseSdpAck(request, content.toString(), platform); // tcp涓诲姩妯″紡锛屽洖澶峴dp鍚庡紑鍚洃鍚� if (sendRtpItem.isTcpActive()) { - MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); + MediaServer mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); Map<String, Object> param = new HashMap<>(12); param.put("vhost","__defaultVhost__"); param.put("app",sendRtpItem.getApp()); - param.put("stream",sendRtpItem.getStreamId()); + param.put("stream",sendRtpItem.getStream()); param.put("ssrc", sendRtpItem.getSsrc()); if (!sendRtpItem.isTcpActive()) { param.put("dst_url",sendRtpItem.getIp()); @@ -436,7 +474,7 @@ // 寮�鍚痳tcp淇濇椿 param.put("udp_rtcp_timeout", sendRtpItem.isRtcp()? "1":"0"); } - JSONObject startSendRtpStreamResult = zlmServerFactory.startSendRtpStreamForPassive(mediaInfo, param); + JSONObject startSendRtpStreamResult = zlmServerFactory.startSendRtpPassive(mediaInfo, param); if (startSendRtpStreamResult != null) { startSendRtpStreamHand(evt, sendRtpItem, null, startSendRtpStreamResult, param, callIdHeader); } @@ -452,7 +490,7 @@ Response response = getMessageFactory().createResponse(statusCode, evt.getRequest()); sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response); } - } catch (ParseException | SipException e) { + } catch (ParseException | SipException e) { logger.error("鏈鐞嗙殑寮傚父 ", e); } }); @@ -462,20 +500,20 @@ String startTimeStr = DateUtil.urlFormatter.format(start); String endTimeStr = DateUtil.urlFormatter.format(end); String stream = device.getDeviceId() + "_" + channelId + "_" + startTimeStr + "_" + endTimeStr; - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, stream, null, device.isSsrcCheck(), true, 0, false, device.getStreamModeForParam()); - sendRtpItem.setStreamId(ssrcInfo.getStream()); + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, stream, null, device.isSsrcCheck(), true, 0,false,!channel.isHasAudio(), false, device.getStreamModeForParam()); + sendRtpItem.setStream(stream); // 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶� redisCatchStorage.updateSendRTPSever(sendRtpItem); playService.playBack(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, DateUtil.formatter.format(start), DateUtil.formatter.format(end), (code, msg, data) -> { - if (code == InviteErrorCode.SUCCESS.getCode()){ + if (code == InviteErrorCode.SUCCESS.getCode()) { hookEvent.run(code, msg, data); - }else if (code == InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode() || code == InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode()){ + } else if (code == InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode() || code == InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode()) { logger.info("[褰曞儚鍥炴斁]瓒呮椂, 鐢ㄦ埛锛歿}锛� 閫氶亾锛歿}", username, channelId); redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null); errorEvent.run(code, msg, data); - }else { + } else { errorEvent.run(code, msg, data); } }); @@ -492,8 +530,8 @@ } sendRtpItem.setPlayType(InviteStreamType.DOWNLOAD); - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, null, device.isSsrcCheck(), true, 0, false, device.getStreamModeForParam()); - sendRtpItem.setStreamId(ssrcInfo.getStream()); + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, null, device.isSsrcCheck(), true, 0, false,!channel.isHasAudio(), false, device.getStreamModeForParam()); + sendRtpItem.setStream(ssrcInfo.getStream()); // 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶� redisCatchStorage.updateSendRTPSever(sendRtpItem); playService.download(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, DateUtil.formatter.format(start), @@ -510,7 +548,10 @@ } }); } else { - + sendRtpItem.setPlayType(InviteStreamType.PLAY); + String streamId = String.format("%s_%s", device.getDeviceId(), channelId); + sendRtpItem.setStream(streamId); + redisCatchStorage.updateSendRTPSever(sendRtpItem); SSRCInfo ssrcInfo = playService.play(mediaServerItem, device.getDeviceId(), channelId, ssrc, ((code, msg, data) -> { if (code == InviteErrorCode.SUCCESS.getCode()) { hookEvent.run(code, msg, data); @@ -522,9 +563,6 @@ errorEvent.run(code, msg, data); } })); - sendRtpItem.setPlayType(InviteStreamType.PLAY); - String streamId = String.format("%s_%s", device.getDeviceId(), channelId); - sendRtpItem.setStreamId(streamId); sendRtpItem.setSsrc(ssrcInfo.getSsrc()); redisCatchStorage.updateSendRTPSever(sendRtpItem); @@ -539,24 +577,24 @@ ssrc = gb28181Sdp.getSsrc(); } - if("push".equals(gbStream.getStreamType())) { + if ("push".equals(gbStream.getStreamType())) { if (streamPushItem != null && streamPushItem.isPushIng()) { // 鎺ㄦ祦鐘舵�� pushStream(evt, request, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); } else { // 鏈帹娴� 鎷夎捣 - notifyStreamOnline(evt, request,gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, + notifyStreamOnline(evt, request, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); } - }else if ("proxy".equals(gbStream.getStreamType())){ + } else if ("proxy".equals(gbStream.getStreamType())) { if (null != proxyByAppAndStream) { - if(proxyByAppAndStream.isStatus()){ - pushProxyStream(evt, request, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive, + if (proxyByAppAndStream.isStatus()) { + pushProxyStream(evt, request, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive, mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); - }else{ + } else { //寮�鍚唬鐞嗘媺娴� - notifyStreamOnline(evt, request,gbStream, null, platform, callIdHeader, mediaServerItem, port, tcpActive, + notifyStreamOnline(evt, request, gbStream, null, platform, callIdHeader, mediaServerItem, port, tcpActive, mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); } } @@ -588,7 +626,7 @@ * 瀹夋帓鎺ㄦ祦 */ private void pushProxyStream(RequestEvent evt, SIPRequest request, GbStream gbStream, ParentPlatform platform, - CallIdHeader callIdHeader, MediaServerItem mediaServerItem, + CallIdHeader callIdHeader, MediaServer mediaServerItem, int port, Boolean tcpActive, boolean mediaTransmissionTCP, String channelId, String addressStr, String ssrc, String requesterId) { Boolean streamReady = zlmServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream()); @@ -597,35 +635,36 @@ SendRtpItem sendRtpItem = zlmServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp()); - if (sendRtpItem == null) { - logger.warn("鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�"); - try { - responseAck(request, Response.BUSY_HERE); - } catch (SipException | InvalidArgumentException | ParseException e) { - logger.error("[鍛戒护鍙戦�佸け璐 invite 鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�: {}", e.getMessage()); - } - return; + if (sendRtpItem == null) { + logger.warn("鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�"); + try { + responseAck(request, Response.BUSY_HERE); + } catch (SipException | InvalidArgumentException | ParseException e) { + logger.error("[鍛戒护鍙戦�佸け璐 invite 鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�: {}", e.getMessage()); } - if (tcpActive != null) { - sendRtpItem.setTcpActive(tcpActive); - } - sendRtpItem.setPlayType(InviteStreamType.PUSH); - // 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶� - sendRtpItem.setStatus(1); - sendRtpItem.setCallId(callIdHeader.getCallId()); - sendRtpItem.setFromTag(request.getFromTag()); + return; + } + if (tcpActive != null) { + sendRtpItem.setTcpActive(tcpActive); + } + sendRtpItem.setPlayType(InviteStreamType.PUSH); + // 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶� + sendRtpItem.setStatus(1); + sendRtpItem.setCallId(callIdHeader.getCallId()); + sendRtpItem.setFromTag(request.getFromTag()); - SIPResponse response = sendStreamAck(mediaServerItem, request, sendRtpItem, platform, evt); - if (response != null) { - sendRtpItem.setToTag(response.getToTag()); - } - redisCatchStorage.updateSendRTPSever(sendRtpItem); + SIPResponse response = sendStreamAck(mediaServerItem, request, sendRtpItem, platform, evt); + if (response != null) { + sendRtpItem.setToTag(response.getToTag()); + } + redisCatchStorage.updateSendRTPSever(sendRtpItem); } } + private void pushStream(RequestEvent evt, SIPRequest request, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform, - CallIdHeader callIdHeader, MediaServerItem mediaServerItem, + CallIdHeader callIdHeader, MediaServer mediaServerItem, int port, Boolean tcpActive, boolean mediaTransmissionTCP, String channelId, String addressStr, String ssrc, String requesterId) { // 鎺ㄦ祦 @@ -658,12 +697,11 @@ if (response != null) { sendRtpItem.setToTag(response.getToTag()); } - redisCatchStorage.updateSendRTPSever(sendRtpItem); } else { // 涓嶅湪绾� 鎷夎捣 - notifyStreamOnline(evt, request,gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, + notifyStreamOnline(evt, request, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); } @@ -673,28 +711,28 @@ mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); } } + /** * 閫氱煡娴佷笂绾� */ private void notifyStreamOnline(RequestEvent evt, SIPRequest request, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform, - CallIdHeader callIdHeader, MediaServerItem mediaServerItem, + CallIdHeader callIdHeader, MediaServer mediaServerItem, int port, Boolean tcpActive, boolean mediaTransmissionTCP, String channelId, String addressStr, String ssrc, String requesterId) { if ("proxy".equals(gbStream.getStreamType())) { // TODO 鎺у埗鍚敤浠ヤ娇璁惧涓婄嚎 logger.info("[ app={}, stream={} ]閫氶亾鏈帹娴侊紝鍚敤娴佸悗寮�濮嬫帹娴�", gbStream.getApp(), gbStream.getStream()); // 鐩戝惉娴佷笂绾� - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed(gbStream.getApp(), gbStream.getStream(), true, "rtsp", mediaServerItem.getId()); - zlmHttpHookSubscribe.addSubscribe(hookSubscribe, (mediaServerItemInUSe, hookParam) -> { - OnStreamChangedHookParam streamChangedHookParam = (OnStreamChangedHookParam)hookParam; - logger.info("[涓婄骇鐐规挱]鎷夋祦浠g悊宸茬粡灏辩华锛� {}/{}", streamChangedHookParam.getApp(), streamChangedHookParam.getStream()); + Hook hook = Hook.getInstance(HookType.on_media_arrival, gbStream.getApp(), gbStream.getStream(), mediaServerItem.getId()); + this.hookSubscribe.addSubscribe(hook, (hookData) -> { + logger.info("[涓婄骇鐐规挱]鎷夋祦浠g悊宸茬粡灏辩华锛� {}/{}", hookData.getApp(), hookData.getStream()); dynamicTask.stop(callIdHeader.getCallId()); - pushProxyStream(evt, request, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive, + pushProxyStream(evt, request, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive, mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); }); dynamicTask.startDelay(callIdHeader.getCallId(), () -> { logger.info("[ app={}, stream={} ] 绛夊緟鎷夋祦浠g悊娴佽秴鏃�", gbStream.getApp(), gbStream.getStream()); - zlmHttpHookSubscribe.removeSubscribe(hookSubscribe); + this.hookSubscribe.removeSubscribe(hook); }, userSetting.getPlatformPlayTimeout()); boolean start = streamProxyService.start(gbStream.getApp(), gbStream.getStream()); if (!start) { @@ -703,12 +741,9 @@ } catch (SipException | InvalidArgumentException | ParseException e) { logger.error("[鍛戒护鍙戦�佸け璐 invite 閫氶亾鏈帹娴�: {}", e.getMessage()); } - zlmHttpHookSubscribe.removeSubscribe(hookSubscribe); + this.hookSubscribe.removeSubscribe(hook); dynamicTask.stop(callIdHeader.getCallId()); } - - - } else if ("push".equals(gbStream.getStreamType())) { if (!platform.isStartOfflinePush()) { // 骞冲彴璁剧疆涓叧闂簡鎷夎捣绂荤嚎鐨勬帹娴佸垯鐩存帴鍥炲 @@ -731,13 +766,10 @@ dynamicTask.startDelay(callIdHeader.getCallId(), () -> { logger.info("[ app={}, stream={} ] 绛夊緟璁惧寮�濮嬫帹娴佽秴鏃�", gbStream.getApp(), gbStream.getStream()); try { + redisPushStreamResponseListener.removeEvent(gbStream.getApp(), gbStream.getStream()); mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream()); responseAck(request, Response.REQUEST_TIMEOUT); // 瓒呮椂 - } catch (SipException e) { - logger.error("鏈鐞嗙殑寮傚父 ", e); - } catch (InvalidArgumentException e) { - logger.error("鏈鐞嗙殑寮傚父 ", e); - } catch (ParseException e) { + } catch (SipException | InvalidArgumentException | ParseException e) { logger.error("鏈鐞嗙殑寮傚父 ", e); } }, userSetting.getPlatformPlayTimeout()); @@ -748,6 +780,7 @@ // 娣诲姞鍦ㄦ湰鏈轰笂绾跨殑閫氱煡 mediaListManager.addChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream(), (app, stream, serverId) -> { dynamicTask.stop(callIdHeader.getCallId()); + redisPushStreamResponseListener.removeEvent(gbStream.getApp(), gbStream.getStream()); if (serverId.equals(userSetting.getServerId())) { SendRtpItem sendRtpItem = zlmServerFactory.createSendRtpItem(mediaServerItem, addressStr, finalPort, ssrc, requesterId, app, stream, channelId, mediaTransmissionTCP, platform.isRtcp()); @@ -805,14 +838,14 @@ * 鏉ヨ嚜鍏朵粬wvp鐨勬帹娴� */ private void otherWvpPushStream(RequestEvent evt, SIPRequest request, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform, - CallIdHeader callIdHeader, MediaServerItem mediaServerItem, + CallIdHeader callIdHeader, MediaServer mediaServerItem, int port, Boolean tcpActive, boolean mediaTransmissionTCP, String channelId, String addressStr, String ssrc, String requesterId) { logger.info("[绾ц仈鐐规挱]鐩存挱娴佹潵鑷叾浠栧钩鍙帮紝鍙戦�乺edis娑堟伅"); // 鍙戦�乺edis娑堟伅 redisGbPlayMsgListener.sendMsg(streamPushItem.getServerId(), streamPushItem.getMediaServerId(), streamPushItem.getApp(), streamPushItem.getStream(), addressStr, port, ssrc, requesterId, - channelId, mediaTransmissionTCP, platform.isRtcp(),null, responseSendItemMsg -> { + channelId, mediaTransmissionTCP, platform.isRtcp(),platform.getName(), responseSendItemMsg -> { SendRtpItem sendRtpItem = responseSendItemMsg.getSendRtpItem(); if (sendRtpItem == null || responseSendItemMsg.getMediaServerItem() == null) { logger.warn("鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�"); @@ -837,7 +870,7 @@ sendRtpItem.setCallId(callIdHeader.getCallId()); sendRtpItem.setFromTag(request.getFromTag()); - SIPResponse response = sendStreamAck(responseSendItemMsg.getMediaServerItem(), request,sendRtpItem, platform, evt); + SIPResponse response = sendStreamAck(responseSendItemMsg.getMediaServerItem(), request, sendRtpItem, platform, evt); if (response != null) { sendRtpItem.setToTag(response.getToTag()); } @@ -868,7 +901,7 @@ }); } - public SIPResponse sendStreamAck(MediaServerItem mediaServerItem, SIPRequest request, SendRtpItem sendRtpItem, ParentPlatform platform, RequestEvent evt) { + public SIPResponse sendStreamAck(MediaServer mediaServerItem, SIPRequest request, SendRtpItem sendRtpItem, ParentPlatform platform, RequestEvent evt) { StringBuffer content = new StringBuffer(200); content.append("v=0\r\n"); @@ -878,8 +911,7 @@ content.append("t=0 0\r\n"); // 闈炰弗鏍兼ā寮忕鍙d笉缁熶竴, 澧炲姞鍏煎鎬э紝淇敼涓轰竴涓笉涓�0鐨勭鍙� int localPort = sendRtpItem.getLocalPort(); - if(localPort == 0) - { + if (localPort == 0) { localPort = new Random().nextInt(65535) + 1; } content.append("m=video " + localPort + " RTP/AVP 96\r\n"); @@ -898,39 +930,78 @@ try { return responseSdpAck(request, content.toString(), platform); - } catch (SipException e) { - logger.error("鏈鐞嗙殑寮傚父 ", e); - } catch (InvalidArgumentException e) { - logger.error("鏈鐞嗙殑寮傚父 ", e); - } catch (ParseException e) { + } catch (SipException | InvalidArgumentException | ParseException e) { logger.error("鏈鐞嗙殑寮傚父 ", e); } return null; } - public void inviteFromDeviceHandle(SIPRequest request, String requesterId) { + public void inviteFromDeviceHandle(SIPRequest request, String requesterId, String channelId) { + + String realChannelId = null; // 闈炰笂绾у钩鍙拌姹傦紝鏌ヨ鏄惁璁惧璇锋眰锛堥�氬父涓烘帴鏀惰闊冲箍鎾殑璁惧锛� Device device = redisCatchStorage.getDevice(requesterId); + // 鍒ゆ柇requesterId鏄澶囪繕鏄�氶亾 + if (device == null) { + device = storager.queryVideoDeviceByChannelId(requesterId); + realChannelId = requesterId; + }else { + realChannelId = channelId; + } + if (device == null) { + // 妫�鏌hannelID鏄惁鍙敤 + device = redisCatchStorage.getDevice(channelId); + if (device == null) { + device = storager.queryVideoDeviceByChannelId(channelId); + realChannelId = channelId; + } + } + + if (device == null) { + logger.warn("鏉ヨ嚜璁惧鐨処nvite璇锋眰锛屾棤娉曚粠璇锋眰淇℃伅涓‘瀹氭墍灞炶澶囷紝宸插拷鐣ワ紝requesterId锛� {}/{}", requesterId, channelId); + try { + responseAck(request, Response.FORBIDDEN); + } catch (SipException | InvalidArgumentException | ParseException e) { + logger.error("[鍛戒护鍙戦�佸け璐 鏉ヨ嚜璁惧鐨処nvite璇锋眰锛屾棤娉曚粠璇锋眰淇℃伅涓‘瀹氭墍灞炶澶� FORBIDDEN: {}", e.getMessage()); + } + return; + } + + AudioBroadcastCatch broadcastCatch = audioBroadcastManager.get(device.getDeviceId(), realChannelId); + if (broadcastCatch == null) { + logger.warn("鏉ヨ嚜璁惧鐨処nvite璇锋眰闈炶闊冲箍鎾紝宸插拷鐣ワ紝requesterId锛� {}/{}", requesterId, channelId); + try { + responseAck(request, Response.FORBIDDEN); + } catch (SipException | InvalidArgumentException | ParseException e) { + logger.error("[鍛戒护鍙戦�佸け璐 鏉ヨ嚜璁惧鐨処nvite璇锋眰闈炶闊冲箍鎾� FORBIDDEN: {}", e.getMessage()); + } + return; + } if (device != null) { logger.info("鏀跺埌璁惧" + requesterId + "鐨勮闊冲箍鎾璉nvite璇锋眰"); + String key = VideoManagerConstants.BROADCAST_WAITE_INVITE + device.getDeviceId(); + if (!SipUtils.isFrontEnd(device.getDeviceId())) { + key += broadcastCatch.getChannelId(); + } + dynamicTask.stop(key); try { responseAck(request, Response.TRYING); } catch (SipException | InvalidArgumentException | ParseException e) { logger.error("[鍛戒护鍙戦�佸け璐 invite BAD_REQUEST: {}", e.getMessage()); + playService.stopAudioBroadcast(device.getDeviceId(), broadcastCatch.getChannelId()); + return; } String contentString = new String(request.getRawContent()); - // jainSip涓嶆敮鎸亂=瀛楁锛� 绉婚櫎绉婚櫎浠ヨВ鏋愩�� - String ssrc = "0000000404"; try { Gb28181Sdp gb28181Sdp = SipUtils.parseSDP(contentString); SessionDescription sdp = gb28181Sdp.getBaseSdb(); // 鑾峰彇鏀寔鐨勬牸寮� Vector mediaDescriptions = sdp.getMediaDescriptions(true); + // 鏌ョ湅鏄惁鏀寔PS 璐熻浇96 int port = -1; - //boolean recvonly = false; boolean mediaTransmissionTCP = false; Boolean tcpActive = null; for (int i = 0; i < mediaDescriptions.size(); i++) { @@ -938,7 +1009,7 @@ Media media = mediaDescription.getMedia(); Vector mediaFormats = media.getMediaFormats(false); - if (mediaFormats.contains("8")) { +// if (mediaFormats.contains("8")) { port = media.getMediaPort(); String protocol = media.getProtocol(); // 鍖哄垎TCP鍙戞祦杩樻槸udp锛� 褰撳墠榛樿udp @@ -954,7 +1025,7 @@ } } break; - } +// } } if (port == -1) { logger.info("涓嶆敮鎸佺殑濯掍綋鏍煎紡锛岃繑鍥�415"); @@ -962,26 +1033,147 @@ try { responseAck(request, Response.UNSUPPORTED_MEDIA_TYPE); // 涓嶆敮鎸佺殑鏍煎紡锛屽彂415 } catch (SipException | InvalidArgumentException | ParseException e) { - logger.error("[鍛戒护鍙戦�佸け璐 invite 涓嶆敮鎸佺殑濯掍綋鏍煎紡锛岃繑鍥�415锛� {}", e.getMessage()); + logger.error("[鍛戒护鍙戦�佸け璐 invite 涓嶆敮鎸佺殑濯掍綋鏍煎紡: {}", e.getMessage()); + playService.stopAudioBroadcast(device.getDeviceId(), broadcastCatch.getChannelId()); + return; } return; } - String username = sdp.getOrigin().getUsername(); - String addressStr = sdp.getConnection().getAddress(); - logger.info("璁惧{}璇锋眰璇煶娴侊紝鍦板潃锛歿}:{}锛宻src锛歿}", username, addressStr, port, ssrc); + String addressStr = sdp.getOrigin().getAddress(); + logger.info("璁惧{}璇锋眰璇煶娴侊紝鍦板潃锛歿}:{}锛宻src锛歿}, {}", requesterId, addressStr, port, gb28181Sdp.getSsrc(), + mediaTransmissionTCP ? (tcpActive ? "TCP涓诲姩" : "TCP琚姩") : "UDP"); + + MediaServer mediaServerItem = broadcastCatch.getMediaServerItem(); + if (mediaServerItem == null) { + logger.warn("鏈壘鍒拌闊冲枈璇濅娇鐢ㄧ殑zlm"); + try { + responseAck(request, Response.BUSY_HERE); + } catch (SipException | InvalidArgumentException | ParseException e) { + logger.error("[鍛戒护鍙戦�佸け璐 invite 鏈壘鍒板彲鐢ㄧ殑zlm: {}", e.getMessage()); + playService.stopAudioBroadcast(device.getDeviceId(), broadcastCatch.getChannelId()); + } + return; + } + logger.info("璁惧{}璇锋眰璇煶娴侊紝 鏀舵祦鍦板潃锛歿}:{}锛宻src锛歿}, {}, 瀵硅鏂瑰紡锛歿}", requesterId, addressStr, port, gb28181Sdp.getSsrc(), + mediaTransmissionTCP ? (tcpActive ? "TCP涓诲姩" : "TCP琚姩") : "UDP", sdp.getSessionName().getValue()); + CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME); + + SendRtpItem sendRtpItem = zlmServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, gb28181Sdp.getSsrc(), requesterId, + device.getDeviceId(), broadcastCatch.getChannelId(), + mediaTransmissionTCP, false); + + if (sendRtpItem == null) { + logger.warn("鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�"); + try { + responseAck(request, Response.BUSY_HERE); + } catch (SipException | InvalidArgumentException | ParseException e) { + logger.error("[鍛戒护鍙戦�佸け璐 invite 鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�: {}", e.getMessage()); + playService.stopAudioBroadcast(device.getDeviceId(), broadcastCatch.getChannelId()); + return; + } + return; + } + + + sendRtpItem.setPlayType(InviteStreamType.BROADCAST); + sendRtpItem.setCallId(callIdHeader.getCallId()); + sendRtpItem.setPlatformId(requesterId); + sendRtpItem.setStatus(1); + sendRtpItem.setApp(broadcastCatch.getApp()); + sendRtpItem.setStream(broadcastCatch.getStream()); + sendRtpItem.setPt(8); + sendRtpItem.setUsePs(false); + sendRtpItem.setRtcp(false); + sendRtpItem.setOnlyAudio(true); + sendRtpItem.setTcp(mediaTransmissionTCP); + if (tcpActive != null) { + sendRtpItem.setTcpActive(tcpActive); + } + + redisCatchStorage.updateSendRTPSever(sendRtpItem); + + Boolean streamReady = zlmServerFactory.isStreamReady(mediaServerItem, broadcastCatch.getApp(), broadcastCatch.getStream()); + if (streamReady) { + sendOk(device, sendRtpItem, sdp, request, mediaServerItem, mediaTransmissionTCP, gb28181Sdp.getSsrc()); + } else { + logger.warn("[璇煶閫氳瘽]锛� 鏈彂鐜板緟鎺ㄩ�佺殑娴�,app={},stream={}", broadcastCatch.getApp(), broadcastCatch.getStream()); + try { + responseAck(request, Response.GONE); + } catch (SipException | InvalidArgumentException | ParseException e) { + logger.error("[鍛戒护鍙戦�佸け璐 璇煶閫氳瘽 鍥炲410澶辫触锛� {}", e.getMessage()); + return; + } + playService.stopAudioBroadcast(device.getDeviceId(), broadcastCatch.getChannelId()); + } } catch (SdpException e) { logger.error("[SDP瑙f瀽寮傚父]", e); + playService.stopAudioBroadcast(device.getDeviceId(), broadcastCatch.getChannelId()); } - - - } else { logger.warn("鏉ヨ嚜鏃犳晥璁惧/骞冲彴鐨勮姹�"); try { - responseAck(request, Response.BAD_REQUEST);; // 涓嶆敮鎸佺殑鏍煎紡锛屽彂415 + responseAck(request, Response.BAD_REQUEST); + ; // 涓嶆敮鎸佺殑鏍煎紡锛屽彂415 } catch (SipException | InvalidArgumentException | ParseException e) { logger.error("[鍛戒护鍙戦�佸け璐 invite 鏉ヨ嚜鏃犳晥璁惧/骞冲彴鐨勮姹傦紝 {}", e.getMessage()); } } } + + SIPResponse sendOk(Device device, SendRtpItem sendRtpItem, SessionDescription sdp, SIPRequest request, MediaServer mediaServerItem, boolean mediaTransmissionTCP, String ssrc) { + SIPResponse sipResponse = null; + try { + sendRtpItem.setStatus(2); + redisCatchStorage.updateSendRTPSever(sendRtpItem); + StringBuffer content = new StringBuffer(200); + content.append("v=0\r\n"); + content.append("o=" + config.getId() + " " + sdp.getOrigin().getSessionId() + " " + sdp.getOrigin().getSessionVersion() + " IN IP4 " + mediaServerItem.getSdpIp() + "\r\n"); + content.append("s=Play\r\n"); + content.append("c=IN IP4 " + mediaServerItem.getSdpIp() + "\r\n"); + content.append("t=0 0\r\n"); + + if (mediaTransmissionTCP) { + content.append("m=audio " + sendRtpItem.getLocalPort() + " TCP/RTP/AVP 8\r\n"); + } else { + content.append("m=audio " + sendRtpItem.getLocalPort() + " RTP/AVP 8\r\n"); + } + + content.append("a=rtpmap:8 PCMA/8000/1\r\n"); + + content.append("a=sendonly\r\n"); + if (sendRtpItem.isTcp()) { + content.append("a=connection:new\r\n"); + if (!sendRtpItem.isTcpActive()) { + content.append("a=setup:active\r\n"); + } else { + content.append("a=setup:passive\r\n"); + } + } + content.append("y=" + ssrc + "\r\n"); + content.append("f=v/////a/1/8/1\r\n"); + + ParentPlatform parentPlatform = new ParentPlatform(); + parentPlatform.setServerIP(device.getIp()); + parentPlatform.setServerPort(device.getPort()); + parentPlatform.setServerGBId(device.getDeviceId()); + + sipResponse = responseSdpAck(request, content.toString(), parentPlatform); + + AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(device.getDeviceId(), sendRtpItem.getChannelId()); + + audioBroadcastCatch.setStatus(AudioBroadcastCatchStatus.Ok); + audioBroadcastCatch.setSipTransactionInfoByRequset(sipResponse); + audioBroadcastManager.update(audioBroadcastCatch); + streamSession.put(device.getDeviceId(), sendRtpItem.getChannelId(), request.getCallIdHeader().getCallId(), sendRtpItem.getStream(), sendRtpItem.getSsrc(), sendRtpItem.getMediaServerId(), sipResponse, InviteSessionType.BROADCAST); + // 寮�鍚彂娴侊紝澶у崕鍦ㄦ敹鍒�200OK鍚庡氨浼氬紑濮嬪缓绔嬭繛鎺� + if (!device.isBroadcastPushAfterAck()) { + logger.info("[璇煶鍠婅瘽] 鍥炲200OK鍚庡彂鐜� BroadcastPushAfterAck涓篎alse锛岀幇鍦ㄥ紑濮嬫帹娴�"); + playService.startPushStream(sendRtpItem, sipResponse, parentPlatform, request.getCallIdHeader()); + } + + } catch (SipException | InvalidArgumentException | ParseException | SdpParseException e) { + logger.error("[鍛戒护鍙戦�佸け璐 璇煶鍠婅瘽 鍥炲200OK锛圫DP锛�: {}", e.getMessage()); + } + return sipResponse; + } } -- Gitblit v1.8.0