| | |
| | | private ZLMRESTfulUtils zlmresTfulUtils; |
| | | |
| | | @Autowired |
| | | private ZLMServerFactory ZLMServerFactory; |
| | | private ZLMServerFactory zlmServerFactory; |
| | | |
| | | @Autowired |
| | | private AssistRESTfulUtils assistRESTfulUtils; |
| | |
| | | |
| | | |
| | | @Override |
| | | public SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, ErrorCallback<Object> callback) { |
| | | public SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<Object> callback) { |
| | | if (mediaServerItem == null) { |
| | | throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到可用的zlm"); |
| | | } |
| | |
| | | String mediaServerId = streamInfo.getMediaServerId(); |
| | | MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); |
| | | |
| | | Boolean ready = ZLMServerFactory.isStreamReady(mediaInfo, "rtp", streamId); |
| | | Boolean ready = zlmServerFactory.isStreamReady(mediaInfo, "rtp", streamId); |
| | | if (ready != null && ready) { |
| | | callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo); |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | String streamId = String.format("%s_%s", device.getDeviceId(), channelId); |
| | | SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, device.isSsrcCheck(), false, 0, false, device.getStreamModeForParam()); |
| | | String streamId = null; |
| | | if (mediaServerItem.isRtpEnable()) { |
| | | streamId = String.format("%s_%s", device.getDeviceId(), channelId); |
| | | } |
| | | SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, ssrc, device.isSsrcCheck(), false, 0, false, device.getStreamModeForParam()); |
| | | if (ssrcInfo == null) { |
| | | callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getMsg(), null); |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, |
| | |
| | | InviteErrorCode.SUCCESS.getCode(), |
| | | InviteErrorCode.SUCCESS.getMsg(), |
| | | streamInfo); |
| | | logger.info("[点播成功] deviceId: {}, channelId:{}, 码流类型:{}", device.getDeviceId(), |
| | | logger.info("[点播成功] deviceId: {}, channelId:{}, 码流类型:{}", device.getDeviceId(), channelId, |
| | | device.isSwitchPrimarySubStream() ? "辅码流" : "主码流"); |
| | | String streamUrl; |
| | | if (mediaServerItemInuse.getRtspPort() != 0) { |
| | | streamUrl = String.format("rtsp://127.0.0.1:%s/%s/%s", mediaServerItemInuse.getRtspPort(), "rtp", ssrcInfo.getStream()); |
| | | }else { |
| | | streamUrl = String.format("http://127.0.0.1:%s/%s/%s.live.mp4", mediaServerItemInuse.getHttpPort(), "rtp", ssrcInfo.getStream()); |
| | | } |
| | | String path = "snap"; |
| | | String fileName = device.getDeviceId() + "_" + channelId + ".jpg"; |
| | | // 请求截图 |
| | | logger.info("[请求截图]: " + fileName); |
| | | zlmresTfulUtils.getSnap(mediaServerItemInuse, streamUrl, 15, 1, path, fileName); |
| | | |
| | | snapOnPlay(mediaServerItemInuse, device.getDeviceId(), channelId, ssrcInfo.getStream()); |
| | | }, (event) -> { |
| | | inviteInfo.setStatus(InviteSessionStatus.ok); |
| | | |
| | |
| | | // 查询到ssrc不一致且开启了ssrc校验则需要针对处理 |
| | | if (ssrcInfo.getSsrc().equals(ssrcInResponse)) { |
| | | if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE")) { |
| | | String substring = contentString.substring(0, contentString.indexOf("y=")); |
| | | try { |
| | | SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring); |
| | | int port = -1; |
| | | Vector mediaDescriptions = sdp.getMediaDescriptions(true); |
| | | for (Object description : mediaDescriptions) { |
| | | MediaDescription mediaDescription = (MediaDescription) description; |
| | | Media media = mediaDescription.getMedia(); |
| | | |
| | | Vector mediaFormats = media.getMediaFormats(false); |
| | | if (mediaFormats.contains("96")) { |
| | | port = media.getMediaPort(); |
| | | break; |
| | | } |
| | | } |
| | | logger.info("[点播-TCP主动连接对方] deviceId: {}, channelId: {}, 连接对方的地址:{}:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, sdp.getConnection().getAddress(), port, device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); |
| | | JSONObject jsonObject = zlmresTfulUtils.connectRtpServer(mediaServerItem, sdp.getConnection().getAddress(), port, ssrcInfo.getStream()); |
| | | logger.info("[点播-TCP主动连接对方] 结果: {}", jsonObject); |
| | | } catch (SdpException e) { |
| | | logger.error("[点播-TCP主动连接对方] deviceId: {}, channelId: {}, 解析200OK的SDP信息失败", device.getDeviceId(), channelId, e); |
| | | dynamicTask.stop(timeOutTaskKey); |
| | | mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); |
| | | // 释放ssrc |
| | | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); |
| | | |
| | | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); |
| | | |
| | | callback.run(InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(), |
| | | InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null); |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, |
| | | InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(), |
| | | InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null); |
| | | } |
| | | tcpActiveHandler(device, channelId, contentString, mediaServerItem, timeOutTaskKey, ssrcInfo, callback); |
| | | } |
| | | return; |
| | | } |
| | |
| | | InviteErrorCode.SUCCESS.getCode(), |
| | | InviteErrorCode.SUCCESS.getMsg(), |
| | | streamInfo); |
| | | snapOnPlay(mediaServerItemInUse, device.getDeviceId(), channelId, stream); |
| | | }); |
| | | return; |
| | | } |
| | |
| | | ssrcInfo.setSsrc(ssrcInResponse); |
| | | inviteInfo.setSsrcInfo(ssrcInfo); |
| | | inviteInfo.setStream(ssrcInfo.getStream()); |
| | | if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE")) { |
| | | tcpActiveHandler(device, channelId, contentString, mediaServerItem, timeOutTaskKey, ssrcInfo, callback); |
| | | } |
| | | } |
| | | }else { |
| | | logger.info("[点播消息] 收到invite 200, 下级自定义了ssrc, 但是当前模式无需修正"); |
| | |
| | | |
| | | inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId); |
| | | } |
| | | } |
| | | |
| | | private void tcpActiveHandler(Device device, String channelId, String contentString, |
| | | MediaServerItem mediaServerItem, |
| | | String timeOutTaskKey, SSRCInfo ssrcInfo, ErrorCallback<Object> callback){ |
| | | if (!device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE")) { |
| | | return; |
| | | } |
| | | String substring = contentString.substring(0, contentString.indexOf("y=")); |
| | | try { |
| | | SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring); |
| | | int port = -1; |
| | | Vector mediaDescriptions = sdp.getMediaDescriptions(true); |
| | | for (Object description : mediaDescriptions) { |
| | | MediaDescription mediaDescription = (MediaDescription) description; |
| | | Media media = mediaDescription.getMedia(); |
| | | |
| | | Vector mediaFormats = media.getMediaFormats(false); |
| | | if (mediaFormats.contains("96")) { |
| | | port = media.getMediaPort(); |
| | | break; |
| | | } |
| | | } |
| | | logger.info("[TCP主动连接对方] deviceId: {}, channelId: {}, 连接对方的地址:{}:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, sdp.getConnection().getAddress(), port, device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); |
| | | JSONObject jsonObject = zlmresTfulUtils.connectRtpServer(mediaServerItem, sdp.getConnection().getAddress(), port, ssrcInfo.getStream()); |
| | | logger.info("[TCP主动连接对方] 结果: {}", jsonObject); |
| | | } catch (SdpException e) { |
| | | logger.error("[TCP主动连接对方] deviceId: {}, channelId: {}, 解析200OK的SDP信息失败", device.getDeviceId(), channelId, e); |
| | | dynamicTask.stop(timeOutTaskKey); |
| | | mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); |
| | | // 释放ssrc |
| | | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); |
| | | |
| | | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); |
| | | |
| | | callback.run(InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(), |
| | | InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null); |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, |
| | | InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(), |
| | | InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 点播成功时调用截图. |
| | | * |
| | | * @param mediaServerItemInuse media |
| | | * @param deviceId 设备 ID |
| | | * @param channelId 通道 ID |
| | | * @param stream ssrc |
| | | */ |
| | | private void snapOnPlay(MediaServerItem mediaServerItemInuse, String deviceId, String channelId, String stream) { |
| | | String streamUrl; |
| | | if (mediaServerItemInuse.getRtspPort() != 0) { |
| | | streamUrl = String.format("rtsp://127.0.0.1:%s/%s/%s", mediaServerItemInuse.getRtspPort(), "rtp", stream); |
| | | } else { |
| | | streamUrl = String.format("http://127.0.0.1:%s/%s/%s.live.mp4", mediaServerItemInuse.getHttpPort(), "rtp", stream); |
| | | } |
| | | String path = "snap"; |
| | | String fileName = deviceId + "_" + channelId + ".jpg"; |
| | | // 请求截图 |
| | | logger.info("[请求截图]: " + fileName); |
| | | zlmresTfulUtils.getSnap(mediaServerItemInuse, streamUrl, 15, 1, path, fileName); |
| | | } |
| | | |
| | | private StreamInfo onPublishHandlerForPlay(MediaServerItem mediaServerItem, HookParam hookParam, String deviceId, String channelId) { |
| | |
| | | return; |
| | | } |
| | | MediaServerItem newMediaServerItem = getNewMediaServerItem(device); |
| | | SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, null, device.isSsrcCheck(), true, 0, false, device.getStreamModeForParam()); |
| | | String stream = null; |
| | | if (newMediaServerItem.isRtpEnable()) { |
| | | String startTimeStr = startTime.replace("-", "") |
| | | .replace(":", "") |
| | | .replace(" ", ""); |
| | | System.out.println(startTimeStr); |
| | | String endTimeTimeStr = endTime.replace("-", "") |
| | | .replace(":", "") |
| | | .replace(" ", ""); |
| | | System.out.println(endTimeTimeStr); |
| | | stream = deviceId + "_" + channelId + "_" + startTimeStr + "_" + endTimeTimeStr; |
| | | } |
| | | SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, stream, null, device.isSsrcCheck(), true, 0, false, device.getStreamModeForParam()); |
| | | playBack(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, callback); |
| | | } |
| | | |
| | |
| | | // 查询到ssrc不一致且开启了ssrc校验则需要针对处理 |
| | | if (ssrcInfo.getSsrc().equals(ssrcInResponse)) { |
| | | if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE")) { |
| | | String substring = contentString.substring(0, contentString.indexOf("y=")); |
| | | try { |
| | | SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring); |
| | | int port = -1; |
| | | Vector mediaDescriptions = sdp.getMediaDescriptions(true); |
| | | for (Object description : mediaDescriptions) { |
| | | MediaDescription mediaDescription = (MediaDescription) description; |
| | | Media media = mediaDescription.getMedia(); |
| | | |
| | | Vector mediaFormats = media.getMediaFormats(false); |
| | | if (mediaFormats.contains("96")) { |
| | | port = media.getMediaPort(); |
| | | break; |
| | | } |
| | | } |
| | | logger.info("[录像回放-TCP主动连接对方] deviceId: {}, channelId: {}, 连接对方的地址:{}:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, sdp.getConnection().getAddress(), port, device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); |
| | | JSONObject jsonObject = zlmresTfulUtils.connectRtpServer(mediaServerItem, sdp.getConnection().getAddress(), port, ssrcInfo.getStream()); |
| | | logger.info("[录像回放-TCP主动连接对方] 结果: {}", jsonObject); |
| | | } catch (SdpException e) { |
| | | logger.error("[录像回放-TCP主动连接对方] deviceId: {}, channelId: {}, 解析200OK的SDP信息失败", device.getDeviceId(), channelId, e); |
| | | dynamicTask.stop(playBackTimeOutTaskKey); |
| | | mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); |
| | | // 释放ssrc |
| | | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); |
| | | |
| | | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); |
| | | |
| | | callback.run(InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(), |
| | | InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null); |
| | | inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, |
| | | InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(), |
| | | InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null); |
| | | } |
| | | tcpActiveHandler(device, channelId, contentString, mediaServerItem, playBackTimeOutTaskKey, ssrcInfo, callback); |
| | | } |
| | | return; |
| | | } |
| | |
| | | ssrcInfo.setSsrc(ssrcInResponse); |
| | | inviteInfo.setSsrcInfo(ssrcInfo); |
| | | inviteInfo.setStream(ssrcInfo.getStream()); |
| | | if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE")) { |
| | | tcpActiveHandler(device, channelId, contentString, mediaServerItem, playBackTimeOutTaskKey, ssrcInfo, callback); |
| | | } |
| | | } |
| | | }else { |
| | | logger.info("[点播消息] 收到invite 200, 下级自定义了ssrc, 但是当前模式无需修正"); |
| | |
| | | } |
| | | |
| | | MediaServerItem newMediaServerItem = getNewMediaServerItem(device); |
| | | play(newMediaServerItem, deviceId, channelId, (code, msg, data)->{ |
| | | play(newMediaServerItem, deviceId, channelId, null, (code, msg, data)->{ |
| | | if (code == InviteErrorCode.SUCCESS.getCode()) { |
| | | InviteInfo inviteInfoForPlay = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); |
| | | if (inviteInfoForPlay != null && inviteInfoForPlay.getStreamInfo() != null) { |