| | |
| | | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
| | | import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.*; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; |
| | | import com.genersoft.iot.vmp.service.IMediaServerService; |
| | | import com.genersoft.iot.vmp.service.IPlayService; |
| | | import com.genersoft.iot.vmp.service.IStreamProxyService; |
| | |
| | | return; |
| | | } else { |
| | | streamPushItem = streamPushService.getPush(gbStream.getApp(), gbStream.getStream()); |
| | | if (streamPushItem == null || streamPushItem.getServerId().equals(userSetting.getServerId())) { |
| | | logger.info("[ app={}, stream={} ]找不到zlm {},返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId); |
| | | try { |
| | | responseAck(request, Response.GONE); |
| | | } catch (SipException | InvalidArgumentException | ParseException e) { |
| | | logger.error("[命令发送失败] invite GONE: {}", e.getMessage()); |
| | | } |
| | | return; |
| | | if (streamPushItem != null) { |
| | | mediaServerItem = mediaServerService.getOne(streamPushItem.getMediaServerId()); |
| | | } |
| | | if (mediaServerItem == null) { |
| | | mediaServerItem = mediaServerService.getDefaultMediaServer(); |
| | | } |
| | | } |
| | | } else { |
| | |
| | | // 解析sdp消息, 使用jainsip 自带的sdp解析方式 |
| | | String contentString = new String(request.getRawContent()); |
| | | |
| | | // jainSip不支持y=字段, 移除以解析。 |
| | | // 检查是否有y字段 |
| | | int ssrcIndex = contentString.indexOf("y="); |
| | | |
| | | SessionDescription sdp; |
| | | if (ssrcIndex >= 0) { |
| | | //ssrc规定长度为10个字节,不取余下长度以避免后续还有“f=”字段 |
| | | String substring = contentString.substring(0, ssrcIndex); |
| | | sdp = SdpFactory.getInstance().createSessionDescription(substring); |
| | | } else { |
| | | sdp = SdpFactory.getInstance().createSessionDescription(contentString); |
| | | } |
| | | Gb28181Sdp gb28181Sdp = SipUtils.parseSDP(contentString); |
| | | SessionDescription sdp = gb28181Sdp.getBaseSdb(); |
| | | String sessionName = sdp.getSessionName().getValue(); |
| | | |
| | | Long startTime = null; |
| | |
| | | } |
| | | |
| | | String ssrc; |
| | | if (userSetting.getUseCustomSsrcForParentInvite() || ssrcIndex < 0) { |
| | | if (userSetting.getUseCustomSsrcForParentInvite() || gb28181Sdp.getSsrc() == null) { |
| | | // 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式 |
| | | ssrc = "Play".equalsIgnoreCase(sessionName) ? ssrcFactory.getPlaySsrc(mediaServerItem.getId()) : ssrcFactory.getPlayBackSsrc(mediaServerItem.getId()); |
| | | }else { |
| | | ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); |
| | | ssrc = gb28181Sdp.getSsrc(); |
| | | } |
| | | String streamTypeStr = null; |
| | | if (mediaTransmissionTCP) { |
| | |
| | | } |
| | | sendRtpItem.setStreamId(streamId); |
| | | redisCatchStorage.updateSendRTPSever(sendRtpItem); |
| | | playService.play(mediaServerItem, device.getDeviceId(), channelId,false, ((code, msg, data) -> { |
| | | playService.play(mediaServerItem, device.getDeviceId(), channelId, ((code, msg, data) -> { |
| | | 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 (gbStream != null) { |
| | | |
| | | String ssrc; |
| | | if (userSetting.getUseCustomSsrcForParentInvite() || ssrcIndex < 0) { |
| | | if (userSetting.getUseCustomSsrcForParentInvite() || gb28181Sdp.getSsrc() == null) { |
| | | // 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式 |
| | | ssrc = "Play".equalsIgnoreCase(sessionName) ? ssrcFactory.getPlaySsrc(mediaServerItem.getId()) : ssrcFactory.getPlayBackSsrc(mediaServerItem.getId()); |
| | | }else { |
| | | ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); |
| | | ssrc = gb28181Sdp.getSsrc(); |
| | | } |
| | | |
| | | if("push".equals(gbStream.getStreamType())) { |
| | |
| | | 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, responseJSON) -> { |
| | | String app = responseJSON.getString("app"); |
| | | String stream = responseJSON.getString("stream"); |
| | | logger.info("[上级点播]拉流代理已经就绪, {}/{}", app, stream); |
| | | zlmHttpHookSubscribe.addSubscribe(hookSubscribe, (mediaServerItemInUSe, hookParam) -> { |
| | | OnStreamChangedHookParam streamChangedHookParam = (OnStreamChangedHookParam)hookParam; |
| | | logger.info("[上级点播]拉流代理已经就绪, {}/{}", streamChangedHookParam.getApp(), streamChangedHookParam.getStream()); |
| | | dynamicTask.stop(callIdHeader.getCallId()); |
| | | pushProxyStream(evt, request, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive, |
| | | mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); |
| | |
| | | } |
| | | String contentString = new String(request.getRawContent()); |
| | | // jainSip不支持y=字段, 移除移除以解析。 |
| | | String substring = contentString; |
| | | String ssrc = "0000000404"; |
| | | int ssrcIndex = contentString.indexOf("y="); |
| | | if (ssrcIndex > 0) { |
| | | substring = contentString.substring(0, ssrcIndex); |
| | | ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); |
| | | } |
| | | ssrcIndex = substring.indexOf("f="); |
| | | if (ssrcIndex > 0) { |
| | | substring = contentString.substring(0, ssrcIndex); |
| | | } |
| | | SessionDescription sdp = null; |
| | | |
| | | try { |
| | | sdp = SdpFactory.getInstance().createSessionDescription(substring); |
| | | Gb28181Sdp gb28181Sdp = SipUtils.parseSDP(contentString); |
| | | SessionDescription sdp = gb28181Sdp.getBaseSdb(); |
| | | // 获取支持的格式 |
| | | Vector mediaDescriptions = sdp.getMediaDescriptions(true); |
| | | // 查看是否支持PS 负载96 |