From 985082d33930868c3cc1723f28fd9aaae9013a8f Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: 星期三, 16 八月 2023 09:11:22 +0800 Subject: [PATCH] 添加缺少的内容 --- src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java | 1047 ++++++++++++++++++++++++++++------------------------------ 1 files changed, 507 insertions(+), 540 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java old mode 100644 new mode 100755 index 96e4098..f2653f7 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java @@ -1,8 +1,9 @@ package com.genersoft.iot.vmp.service.impl; -import com.alibaba.fastjson2.JSON; -import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; +import com.genersoft.iot.vmp.common.InviteInfo; +import com.genersoft.iot.vmp.common.InviteSessionStatus; +import com.genersoft.iot.vmp.common.InviteSessionType; import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.conf.DynamicTask; import com.genersoft.iot.vmp.conf.UserSetting; @@ -11,35 +12,32 @@ import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; -import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; -import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; +import com.genersoft.iot.vmp.gb28181.utils.SipUtils; import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils; import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; +import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; -import com.genersoft.iot.vmp.service.IDeviceService; -import com.genersoft.iot.vmp.service.IMediaServerService; -import com.genersoft.iot.vmp.service.IMediaService; -import com.genersoft.iot.vmp.service.IPlayService; -import com.genersoft.iot.vmp.service.bean.InviteTimeOutCallback; -import com.genersoft.iot.vmp.service.bean.PlayBackCallback; -import com.genersoft.iot.vmp.service.bean.PlayBackResult; +import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam; +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; import com.genersoft.iot.vmp.service.bean.SSRCInfo; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; -import com.genersoft.iot.vmp.vmanager.bean.WVPResult; +import gov.nist.javax.sip.message.SIPResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.util.ObjectUtils; @@ -47,6 +45,7 @@ import javax.sip.InvalidArgumentException; import javax.sip.ResponseEvent; import javax.sip.SipException; +import java.io.File; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.ParseException; @@ -73,10 +72,16 @@ private IRedisCatchStorage redisCatchStorage; @Autowired + private IInviteStreamService inviteStreamService; + + @Autowired private DeferredResultHolder resultHolder; @Autowired private ZLMRESTfulUtils zlmresTfulUtils; + + @Autowired + private ZLMServerFactory zlmServerFactory; @Autowired private AssistRESTfulUtils assistRESTfulUtils; @@ -90,7 +95,6 @@ @Autowired private VideoStreamSessionManager streamSession; - @Autowired private IDeviceService deviceService; @@ -103,145 +107,124 @@ @Autowired private ZlmHttpHookSubscribe subscribe; - @Autowired - private SSRCFactory ssrcFactory; - - @Autowired - private RedisTemplate<Object, Object> redisTemplate; - @Override - public void play(MediaServerItem mediaServerItem, String deviceId, String channelId, - ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, - Runnable timeoutCallback) { + public SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<Object> callback) { if (mediaServerItem == null) { + logger.warn("[鐐规挱] 鏈壘鍒板彲鐢ㄧ殑zlm deviceId: {},channelId:{}", deviceId, channelId); throw new ControllerException(ErrorCode.ERROR100.getCode(), "鏈壘鍒板彲鐢ㄧ殑zlm"); } - String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId; - - RequestMessage msg = new RequestMessage(); - msg.setKey(key); Device device = redisCatchStorage.getDevice(deviceId); - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); + if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE") && !mediaServerItem.isRtpEnable()) { + logger.warn("[鐐规挱] 鍗曠鍙f敹娴佹椂涓嶆敮鎸乀CP涓诲姩鏂瑰紡鏀舵祦 deviceId: {},channelId:{}", deviceId, channelId); + throw new ControllerException(ErrorCode.ERROR100.getCode(), "鍗曠鍙f敹娴佹椂涓嶆敮鎸乀CP涓诲姩鏂瑰紡鏀舵祦"); + } + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); + if (inviteInfo != null ) { + if (inviteInfo.getStreamInfo() == null) { + // 鐐规挱鍙戣捣浜嗕絾鏄皻鏈垚鍔�, 浠呮敞鍐屽洖璋冪瓑寰呯粨鏋滃嵆鍙� + inviteStreamService.once(InviteSessionType.PLAY, deviceId, channelId, null, callback); + logger.info("[鐐规挱寮�濮媇 宸茬粡璇锋眰涓紝绛夊緟缁撴灉锛� deviceId: {}, channelId: {}", device.getDeviceId(), channelId); + return inviteInfo.getSsrcInfo(); + }else { + StreamInfo streamInfo = inviteInfo.getStreamInfo(); + String streamId = streamInfo.getStream(); + if (streamId == null) { + callback.run(InviteErrorCode.ERROR_FOR_CATCH_DATA.getCode(), "鐐规挱澶辫触锛� redis缂撳瓨streamId绛変簬null", null); + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, + InviteErrorCode.ERROR_FOR_CATCH_DATA.getCode(), + "鐐规挱澶辫触锛� redis缂撳瓨streamId绛変簬null", + null); + return inviteInfo.getSsrcInfo(); + } + String mediaServerId = streamInfo.getMediaServerId(); + MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); - if (streamInfo != null) { - String streamId = streamInfo.getStream(); - if (streamId == null) { - WVPResult wvpResult = new WVPResult(); - wvpResult.setCode(ErrorCode.ERROR100.getCode()); - wvpResult.setMsg("鐐规挱澶辫触锛� redis缂撳瓨streamId绛変簬null"); - msg.setData(wvpResult); - resultHolder.invokeAllResult(msg); - return; - } - String mediaServerId = streamInfo.getMediaServerId(); - MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); - - JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId); - if (rtpInfo.getInteger("code") == 0) { - if (rtpInfo.getBoolean("exist")) { - int localPort = rtpInfo.getInteger("local_port"); - if (localPort == 0) { - logger.warn("[鐐规挱]锛岀偣鎾椂鍙戠幇rtpServer瀛樺湪锛屼絾鏄皻鏈紑濮嬫帹娴�"); - // 姝ゆ椂璇存槑rtpServer宸茬粡鍒涘缓浣嗘槸娴佽繕娌℃湁鎺ㄤ笂鏉� - WVPResult wvpResult = new WVPResult(); - wvpResult.setCode(ErrorCode.ERROR100.getCode()); - wvpResult.setMsg("鐐规挱宸茬粡鍦ㄨ繘琛屼腑锛岃绋嶅�欓噸璇�"); - msg.setData(wvpResult); - - resultHolder.invokeAllResult(msg); - return; - } else { - WVPResult wvpResult = new WVPResult(); - wvpResult.setCode(ErrorCode.SUCCESS.getCode()); - wvpResult.setMsg(ErrorCode.SUCCESS.getMsg()); - wvpResult.setData(streamInfo); - msg.setData(wvpResult); - resultHolder.invokeAllResult(msg); - if (hookEvent != null) { - hookEvent.response(mediaServerItem, JSON.parseObject(JSON.toJSONString(streamInfo))); - } - } - - } else { - redisCatchStorage.stopPlay(streamInfo); + 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, + InviteErrorCode.SUCCESS.getCode(), + InviteErrorCode.SUCCESS.getMsg(), + streamInfo); + logger.info("[鐐规挱宸插瓨鍦╙ 鐩存帴杩斿洖锛� deviceId: {}, channelId: {}", device.getDeviceId(), channelId); + return inviteInfo.getSsrcInfo(); + }else { + // 鐐规挱鍙戣捣浜嗕絾鏄皻鏈垚鍔�, 浠呮敞鍐屽洖璋冪瓑寰呯粨鏋滃嵆鍙� + inviteStreamService.once(InviteSessionType.PLAY, deviceId, channelId, null, callback); storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); - streamInfo = null; + inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); } - } else { - //zlm杩炴帴澶辫触 - redisCatchStorage.stopPlay(streamInfo); - storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); - streamInfo = null; - } } - if (streamInfo == null) { - String streamId = null; - if (mediaServerItem.isRtpEnable()) { - streamId = String.format("%s_%s", device.getDeviceId(), channelId); - } - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, device.isSsrcCheck(), false, 0, false, device.getStreamModeForParam()); - if (ssrcInfo == null) { - WVPResult wvpResult = new WVPResult(); - wvpResult.setCode(ErrorCode.ERROR100.getCode()); - wvpResult.setMsg("寮�鍚敹娴佸け璐�"); - msg.setData(wvpResult); - - resultHolder.invokeAllResult(msg); - return; - } - play(mediaServerItem, ssrcInfo, device, channelId, (mediaServerItemInUse, response) -> { - if (hookEvent != null) { - hookEvent.response(mediaServerItem, response); - } - }, event -> { - // sip error閿欒 - WVPResult wvpResult = new WVPResult(); - wvpResult.setCode(ErrorCode.ERROR100.getCode()); - wvpResult.setMsg(String.format("鐐规挱澶辫触锛� 閿欒鐮侊細 %s, %s", event.statusCode, event.msg)); - msg.setData(wvpResult); - resultHolder.invokeAllResult(msg); - if (errorEvent != null) { - errorEvent.response(event); - } - }, (code, msgStr) -> { - // invite鐐规挱瓒呮椂 - WVPResult wvpResult = new WVPResult(); - wvpResult.setCode(ErrorCode.ERROR100.getCode()); - if (code == 0) { - wvpResult.setMsg("鐐规挱瓒呮椂锛岃绋嶅�欓噸璇�"); - } else if (code == 1) { - wvpResult.setMsg("鏀舵祦瓒呮椂锛岃绋嶅�欓噸璇�"); - } - msg.setData(wvpResult); - // 鍥炲涔嬪墠鎵�鏈夌殑鐐规挱璇锋眰 - resultHolder.invokeAllResult(msg); - }); + String 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.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), + InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getMsg(), + null); + return null; } + play(mediaServerItem, ssrcInfo, device, channelId, callback); + return ssrcInfo; } @Override public void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, - ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, - InviteTimeOutCallback timeoutCallback) { + ErrorCallback<Object> callback) { - logger.info("[鐐规挱寮�濮媇 deviceId: {}, channelId: {},鏀舵祦绔彛锛歿}, 鏀舵祦妯″紡锛歿}, SSRC: {}, SSRC鏍¢獙锛歿}", device.getDeviceId(), channelId, ssrcInfo.getPort(), device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); + if (mediaServerItem == null || ssrcInfo == null) { + callback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(), + InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getMsg(), + null); + return; + } + logger.info("[鐐规挱寮�濮媇 deviceId: {}, channelId: {},鐮佹祦绫诲瀷锛歿}, 鏀舵祦绔彛锛� {}, STREAM锛歿}, 鏀舵祦妯″紡锛歿}, SSRC: {}, SSRC鏍¢獙锛歿}", + device.getDeviceId(), channelId, device.isSwitchPrimarySubStream() ? "杈呯爜娴�" : "涓荤爜娴�", ssrcInfo.getPort(), ssrcInfo.getStream(), + device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); + //绔彛鑾峰彇澶辫触鐨剆srcInfo 娌℃湁蹇呰鍙戦�佺偣鎾寚浠� + if (ssrcInfo.getPort() <= 0) { + logger.info("[鐐规挱绔彛鍒嗛厤寮傚父]锛宒eviceId={},channelId={},ssrcInfo={}", device.getDeviceId(), channelId, ssrcInfo); + // 閲婃斁ssrc + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); + + callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "鐐规挱绔彛鍒嗛厤寮傚父", null); + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, + InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "鐐规挱绔彛鍒嗛厤寮傚父", null); + return; + } + + // 鍒濆鍖杛edis涓殑invite娑堟伅鐘舵�� + InviteInfo inviteInfo = InviteInfo.getInviteInfo(device.getDeviceId(), channelId, ssrcInfo.getStream(), ssrcInfo, + mediaServerItem.getSdpIp(), ssrcInfo.getPort(), device.getStreamMode(), InviteSessionType.PLAY, + InviteSessionStatus.ready); + inviteInfo.setSubStream(device.isSwitchPrimarySubStream()); + inviteStreamService.updateInviteInfo(inviteInfo); // 瓒呮椂澶勭悊 String timeOutTaskKey = UUID.randomUUID().toString(); dynamicTask.startDelay(timeOutTaskKey, () -> { // 鎵ц瓒呮椂浠诲姟鏃舵煡璇㈡槸鍚﹀凡缁忔垚鍔燂紝鎴愬姛浜嗗垯涓嶆墽琛岃秴鏃朵换鍔★紝闃叉瓒呮椂浠诲姟鍙栨秷澶辫触鐨勬儏鍐� - if (redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId) == null) { - logger.info("[鐐规挱瓒呮椂] 鏀舵祦瓒呮椂 deviceId: {}, channelId: {}锛岀鍙o細{}, SSRC: {}", device.getDeviceId(), channelId, ssrcInfo.getPort(), ssrcInfo.getSsrc()); - // 鐐规挱瓒呮椂鍥炲BYE 鍚屾椂閲婃斁ssrc浠ュ強姝ゆ鐐规挱鐨勮祫婧� + InviteInfo inviteInfoForTimeOut = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId); + if (inviteInfoForTimeOut == null || inviteInfoForTimeOut.getStreamInfo() == null) { + logger.info("[鐐规挱瓒呮椂] 鏀舵祦瓒呮椂 deviceId: {}, channelId: {},鐮佹祦绫诲瀷锛歿}锛岀鍙o細{}, SSRC: {}", + device.getDeviceId(), channelId, device.isSwitchPrimarySubStream() ? "杈呯爜娴�" : "涓荤爜娴�", + ssrcInfo.getPort(), ssrcInfo.getSsrc()); + + callback.run(InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode(), InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getMsg(), null); + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, + InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode(), InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getMsg(), null); + inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId); + try { cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null); } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) { logger.error("[鐐规挱瓒呮椂]锛� 鍙戦�丅YE澶辫触 {}", e.getMessage()); } finally { - timeoutCallback.run(1, "鏀舵祦瓒呮椂"); mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); @@ -252,132 +235,33 @@ } } }, userSetting.getPlayTimeout()); - //绔彛鑾峰彇澶辫触鐨剆srcInfo 娌℃湁蹇呰鍙戦�佺偣鎾寚浠� - if (ssrcInfo.getPort() <= 0) { - logger.info("[鐐规挱绔彛鍒嗛厤寮傚父]锛宒eviceId={},channelId={},ssrcInfo={}", device.getDeviceId(), channelId, ssrcInfo); - dynamicTask.stop(timeOutTaskKey); - // 閲婃斁ssrc - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); - streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); - RequestMessage msg = new RequestMessage(); - msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAY + device.getDeviceId() + channelId); - msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), "鐐规挱绔彛鍒嗛厤寮傚父")); - resultHolder.invokeAllResult(msg); - return; - } try { - cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> { - logger.info("鏀跺埌璁㈤槄娑堟伅锛� " + response.toJSONString()); + cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (mediaServerItemInuse, hookParam ) -> { + logger.info("鏀跺埌璁㈤槄娑堟伅锛� " + hookParam); dynamicTask.stop(timeOutTaskKey); - // hook鍝嶅簲 - onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId); - hookEvent.response(mediaServerItemInuse, response); - logger.info("[鐐规挱鎴愬姛] deviceId: {}, channelId: {}", device.getDeviceId(), channelId); - 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()); + StreamInfo streamInfo = onPublishHandlerForPlay(mediaServerItemInuse, hookParam, device.getDeviceId(), channelId); + if (streamInfo == null){ + callback.run(InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), + InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null); + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, + InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), + InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null); + return; } - String path = "snap"; - String fileName = device.getDeviceId() + "_" + channelId + ".jpg"; - // 璇锋眰鎴浘 - logger.info("[璇锋眰鎴浘]: " + fileName); - zlmresTfulUtils.getSnap(mediaServerItemInuse, streamUrl, 15, 1, path, fileName); - - }, (event) -> { - ResponseEvent responseEvent = (ResponseEvent) event.event; - String contentString = new String(responseEvent.getResponse().getRawContent()); - // 鑾峰彇ssrc - int ssrcIndex = contentString.indexOf("y="); - // 妫�鏌ユ槸鍚︽湁y瀛楁 - if (ssrcIndex >= 0) { - //ssrc瑙勫畾闀垮害涓�10瀛楄妭锛屼笉鍙栦綑涓嬮暱搴︿互閬垮厤鍚庣画杩樻湁鈥渇=鈥濆瓧娈� TODO 鍚庣画瀵逛笉瑙勮寖鐨勯潪10浣峴src鍏煎 - String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12).trim(); - // 鏌ヨ鍒皊src涓嶄竴鑷翠笖寮�鍚簡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: {}, 瑙f瀽200OK鐨凷DP淇℃伅澶辫触", device.getDeviceId(), channelId, e); - } - } - return; - } - logger.info("[鐐规挱娑堟伅] 鏀跺埌invite 200, 鍙戠幇涓嬬骇鑷畾涔変簡ssrc: {}", ssrcInResponse); - if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { - logger.info("[鐐规挱娑堟伅] SSRC淇 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); - if (!ssrcFactory.checkSsrc(mediaServerItem.getId(),ssrcInResponse)) { - // ssrc 涓嶅彲鐢� - logger.info("[鐐规挱娑堟伅] SSRC淇鏃跺彂鐜皊src涓嶅彲浣跨敤 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); - // 閲婃斁ssrc - ssrcFactory.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); - streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); - event.msg = "涓嬬骇鑷畾涔変簡ssrc,浣嗘槸姝src涓嶅彲鐢�"; - event.statusCode = 400; - errorEvent.response(event); - return; - } - // 鍗曠鍙fā寮弒treamId涔熸湁鍙樺寲锛岄噸鏂拌缃洃鍚嵆鍙� - if (!mediaServerItem.isRtpEnable()) { - // 娣诲姞璁㈤槄 - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId()); - subscribe.removeSubscribe(hookSubscribe); - hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase()); - subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response) -> { - logger.info("[ZLM HOOK] ssrc淇鍚庢敹鍒拌闃呮秷鎭細 " + response.toJSONString()); - dynamicTask.stop(timeOutTaskKey); - // hook鍝嶅簲 - onPublishHandlerForPlay(mediaServerItemInUse, response, device.getDeviceId(), channelId); - hookEvent.response(mediaServerItemInUse, response); - }); - return; - } - - - // 鏇存柊ssrc - Boolean result = mediaServerService.updateRtpServerSSRC(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse); - if (!result) { - try { - logger.warn("[鍋滄鐐规挱] {}/{}", device.getDeviceId(), channelId); - cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null, null); - } catch (InvalidArgumentException | SipException | ParseException | SsrcTransactionNotFoundException e) { - logger.error("[鍛戒护鍙戦�佸け璐 鍋滄鐐规挱锛� 鍙戦�丅YE: {}", e.getMessage()); - throw new ControllerException(ErrorCode.ERROR100.getCode(), "鍛戒护鍙戦�佸け璐�: " + e.getMessage()); - } - - dynamicTask.stop(timeOutTaskKey); - // 閲婃斁ssrc - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); - - streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); - event.msg = "涓嬬骇鑷畾涔変簡ssrc,閲嶆柊璁剧疆鏀舵祦淇℃伅澶辫触"; - event.statusCode = 500; - errorEvent.response(event); - } - }else { - logger.info("[鐐规挱娑堟伅] 鏀跺埌invite 200, 涓嬬骇鑷畾涔変簡ssrc, 浣嗘槸褰撳墠妯″紡鏃犻渶淇"); - } - } + callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo); + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, + InviteErrorCode.SUCCESS.getCode(), + InviteErrorCode.SUCCESS.getMsg(), + streamInfo); + logger.info("[鐐规挱鎴愬姛] deviceId: {}, channelId:{}, 鐮佹祦绫诲瀷锛歿}", device.getDeviceId(), channelId, + device.isSwitchPrimarySubStream() ? "杈呯爜娴�" : "涓荤爜娴�"); + snapOnPlay(mediaServerItemInuse, device.getDeviceId(), channelId, ssrcInfo.getStream()); + }, (eventResult) -> { + // 澶勭悊鏀跺埌200ok鍚庣殑TCP涓诲姩杩炴帴浠ュ強SSRC涓嶄竴鑷寸殑闂 + InviteOKHandler(eventResult, ssrcInfo, mediaServerItem, device, channelId, + timeOutTaskKey, callback, inviteInfo, InviteSessionType.PLAY); }, (event) -> { dynamicTask.stop(timeOutTaskKey); mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); @@ -385,7 +269,14 @@ mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); - errorEvent.response(event); + + callback.run(InviteErrorCode.ERROR_FOR_SIGNALLING_ERROR.getCode(), + String.format("鐐规挱澶辫触锛� 閿欒鐮侊細 %s, %s", event.statusCode, event.msg), null); + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, + InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(), + String.format("鐐规挱澶辫触锛� 閿欒鐮侊細 %s, %s", event.statusCode, event.msg), null); + + inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId); }); } catch (InvalidArgumentException | SipException | ParseException e) { @@ -396,65 +287,123 @@ mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); - SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(); - eventResult.type = SipSubscribe.EventResultType.cmdSendFailEvent; - eventResult.statusCode = -1; - eventResult.msg = "鍛戒护鍙戦�佸け璐�"; - errorEvent.response(eventResult); + + callback.run(InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getCode(), + InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getMsg(), null); + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, + InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getCode(), + InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getMsg(), null); + + inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId); } } - @Override - public void onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId) { - StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId); - RequestMessage msg = new RequestMessage(); - msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + 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: {}, 瑙f瀽200OK鐨凷DP淇℃伅澶辫触", 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) { + StreamInfo streamInfo = null; + Device device = redisCatchStorage.getDevice(deviceId); + OnStreamChangedHookParam streamChangedHookParam = (OnStreamChangedHookParam)hookParam; + streamInfo = onPublishHandler(mediaServerItem, streamChangedHookParam, deviceId, channelId); if (streamInfo != null) { DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); if (deviceChannel != null) { deviceChannel.setStreamId(streamInfo.getStream()); storager.startPlay(deviceId, channelId, streamInfo.getStream()); } - redisCatchStorage.startPlay(streamInfo); - - WVPResult wvpResult = new WVPResult(); - wvpResult.setCode(ErrorCode.SUCCESS.getCode()); - wvpResult.setMsg(ErrorCode.SUCCESS.getMsg()); - wvpResult.setData(streamInfo); - - msg.setData(wvpResult); - resultHolder.invokeAllResult(msg); - - } else { - logger.warn("璁惧棰勮API璋冪敤澶辫触锛�"); - msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), "璁惧棰勮API璋冪敤澶辫触锛�")); - resultHolder.invokeAllResult(msg); + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); + if (inviteInfo != null) { + inviteInfo.setStatus(InviteSessionStatus.ok); + inviteInfo.setStreamInfo(streamInfo); + inviteStreamService.updateInviteInfo(inviteInfo); + } } + return streamInfo; + } - private void onPublishHandlerForPlayback(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, PlayBackCallback playBackCallback) { - - StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId); - PlayBackResult<StreamInfo> playBackResult = new PlayBackResult<>(); + private StreamInfo onPublishHandlerForPlayback(MediaServerItem mediaServerItem, HookParam param, String deviceId, String channelId, String startTime, String endTime) { + OnStreamChangedHookParam streamChangedHookParam = (OnStreamChangedHookParam) param; + StreamInfo streamInfo = onPublishHandler(mediaServerItem, streamChangedHookParam, deviceId, channelId); if (streamInfo != null) { + streamInfo.setStartTime(startTime); + streamInfo.setEndTime(endTime); DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); if (deviceChannel != null) { deviceChannel.setStreamId(streamInfo.getStream()); storager.startPlay(deviceId, channelId, streamInfo.getStream()); } - redisCatchStorage.startPlay(streamInfo); + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAYBACK, deviceId, channelId); + if (inviteInfo != null) { + inviteInfo.setStatus(InviteSessionStatus.ok); + inviteInfo.setStreamInfo(streamInfo); + inviteStreamService.updateInviteInfo(inviteInfo); + } - playBackResult.setCode(ErrorCode.SUCCESS.getCode()); - playBackResult.setMsg(ErrorCode.SUCCESS.getMsg()); - playBackResult.setData(streamInfo); - playBackCallback.call(playBackResult); - } else { - logger.warn("褰曞儚鍥炴斁璋冪敤澶辫触锛�"); - playBackResult.setCode(ErrorCode.ERROR100.getCode()); - playBackResult.setMsg("褰曞儚鍥炴斁璋冪敤澶辫触锛�"); - playBackCallback.call(playBackResult); } + return streamInfo; } @Override @@ -493,23 +442,37 @@ @Override public void playBack(String deviceId, String channelId, String startTime, - String endTime, InviteStreamCallback inviteStreamCallback, - PlayBackCallback callback) { + String endTime, ErrorCallback<Object> callback) { Device device = storager.queryVideoDevice(deviceId); if (device == null) { - return; + logger.warn("[褰曞儚鍥炴斁] 鏈壘鍒拌澶� deviceId: {},channelId:{}", deviceId, channelId); + throw new ControllerException(ErrorCode.ERROR100.getCode(), "鏈壘鍒拌澶囷細" + deviceId); } + MediaServerItem newMediaServerItem = getNewMediaServerItem(device); - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, null, device.isSsrcCheck(), true, 0, false, device.getStreamModeForParam()); - playBack(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, inviteStreamCallback, callback); + if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE") && ! newMediaServerItem.isRtpEnable()) { + logger.warn("[褰曞儚鍥炴斁] 鍗曠鍙f敹娴佹椂涓嶆敮鎸乀CP涓诲姩鏂瑰紡鏀舵祦 deviceId: {},channelId:{}", deviceId, channelId); + throw new ControllerException(ErrorCode.ERROR100.getCode(), "鍗曠鍙f敹娴佹椂涓嶆敮鎸乀CP涓诲姩鏂瑰紡鏀舵祦"); + } + String startTimeStr = startTime.replace("-", "") + .replace(":", "") + .replace(" ", ""); + String endTimeTimeStr = endTime.replace("-", "") + .replace(":", "") + .replace(" ", ""); + String 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); } @Override public void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, - String endTime, InviteStreamCallback infoCallBack, - PlayBackCallback playBackCallback) { + String endTime, ErrorCallback<Object> callback) { if (mediaServerItem == null || ssrcInfo == null) { + callback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(), + InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getMsg(), + null); return; } @@ -517,135 +480,67 @@ if (device == null) { throw new ControllerException(ErrorCode.ERROR100.getCode(), "璁惧锛� " + deviceId + "涓嶅瓨鍦�"); } - logger.info("[鍥炴斁娑堟伅] deviceId: {}, channelId: {},鏀舵祦绔彛锛歿}, 鏀舵祦妯″紡锛歿}, SSRC: {}, SSRC鏍¢獙锛歿}", device.getDeviceId(), channelId, ssrcInfo.getPort(), device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); - PlayBackResult<StreamInfo> playBackResult = new PlayBackResult<>(); + logger.info("[褰曞儚鍥炴斁] deviceId: {}, channelId: {}, 寮�濮嬫椂闂�: {}, 缁撴潫鏃堕棿锛� {}, 鏀舵祦绔彛锛歿}, 鏀舵祦妯″紡锛歿}, SSRC: {}, SSRC鏍¢獙锛歿}", + device.getDeviceId(), channelId, startTime, endTime, ssrcInfo.getPort(), device.getStreamMode(), + ssrcInfo.getSsrc(), device.isSsrcCheck()); + // 鍒濆鍖杛edis涓殑invite娑堟伅鐘舵�� + InviteInfo inviteInfo = InviteInfo.getInviteInfo(device.getDeviceId(), channelId, ssrcInfo.getStream(), ssrcInfo, + mediaServerItem.getSdpIp(), ssrcInfo.getPort(), device.getStreamMode(), InviteSessionType.PLAYBACK, + InviteSessionStatus.ready); + inviteStreamService.updateInviteInfo(inviteInfo); String playBackTimeOutTaskKey = UUID.randomUUID().toString(); dynamicTask.startDelay(playBackTimeOutTaskKey, () -> { - logger.warn(String.format("璁惧鍥炴斁瓒呮椂锛宒eviceId锛�%s 锛宑hannelId锛�%s", deviceId, channelId)); - playBackResult.setCode(ErrorCode.ERROR100.getCode()); - playBackResult.setMsg("鍥炴斁瓒呮椂"); + logger.warn("[褰曞儚鍥炴斁] 瓒呮椂锛宒eviceId锛歿} 锛宑hannelId锛歿}", deviceId, channelId); + inviteStreamService.removeInviteInfo(inviteInfo); + callback.run(InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode(), InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getMsg(), null); try { cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null); } catch (InvalidArgumentException | ParseException | SipException e) { - logger.error("[褰曞儚娴乚鍥炴斁瓒呮椂 鍙戦�丅YE澶辫触 {}", e.getMessage()); + logger.error("[褰曞儚鍥炴斁] 瓒呮椂 鍙戦�丅YE澶辫触 {}", e.getMessage()); } catch (SsrcTransactionNotFoundException e) { // 鐐规挱瓒呮椂鍥炲BYE 鍚屾椂閲婃斁ssrc浠ュ強姝ゆ鐐规挱鐨勮祫婧� mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); streamSession.remove(deviceId, channelId, ssrcInfo.getStream()); } - // 鍥炲涔嬪墠鎵�鏈夌殑鐐规挱璇锋眰 - playBackCallback.call(playBackResult); }, userSetting.getPlayTimeout()); SipSubscribe.Event errorEvent = event -> { + logger.info("[褰曞儚鍥炴斁] 澶辫触锛寋} {}", event.statusCode, event.msg); dynamicTask.stop(playBackTimeOutTaskKey); - playBackResult.setCode(ErrorCode.ERROR100.getCode()); - playBackResult.setMsg(String.format("鍥炴斁澶辫触锛� 閿欒鐮侊細 %s, %s", event.statusCode, event.msg)); - playBackResult.setEvent(event); - playBackCallback.call(playBackResult); + callback.run(InviteErrorCode.ERROR_FOR_SIGNALLING_ERROR.getCode(), + String.format("鍥炴斁澶辫触锛� 閿欒鐮侊細 %s, %s", event.statusCode, event.msg), null); + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); + mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); + inviteStreamService.removeInviteInfo(inviteInfo); }; - InviteStreamCallback hookEvent = (InviteStreamInfo inviteStreamInfo) -> { - logger.info("鏀跺埌鍥炴斁璁㈤槄娑堟伅锛� " + inviteStreamInfo.getResponse().toJSONString()); + ZlmHttpHookSubscribe.Event hookEvent = (mediaServerItemInuse, hookParam) -> { + logger.info("鏀跺埌鍥炴斁璁㈤槄娑堟伅锛� " + hookParam); dynamicTask.stop(playBackTimeOutTaskKey); - StreamInfo streamInfo = onPublishHandler(inviteStreamInfo.getMediaServerItem(), inviteStreamInfo.getResponse(), deviceId, channelId); + StreamInfo streamInfo = onPublishHandlerForPlayback(mediaServerItemInuse, hookParam, deviceId, channelId, startTime, endTime); if (streamInfo == null) { logger.warn("璁惧鍥炴斁API璋冪敤澶辫触锛�"); - playBackResult.setCode(ErrorCode.ERROR100.getCode()); - playBackResult.setMsg("璁惧鍥炴斁API璋冪敤澶辫触锛�"); - playBackCallback.call(playBackResult); + callback.run(InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), + InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null); return; } - redisCatchStorage.startPlayback(streamInfo, inviteStreamInfo.getCallId()); - playBackResult.setCode(ErrorCode.SUCCESS.getCode()); - playBackResult.setMsg(ErrorCode.SUCCESS.getMsg()); - playBackResult.setData(streamInfo); - playBackResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem()); - playBackResult.setResponse(inviteStreamInfo.getResponse()); - playBackCallback.call(playBackResult); + callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo); + logger.info("[褰曞儚鍥炴斁] 鎴愬姛 deviceId: {}, channelId: {}, 寮�濮嬫椂闂�: {}, 缁撴潫鏃堕棿锛� {}", device.getDeviceId(), channelId, startTime, endTime); }; try { - cmder.playbackStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, infoCallBack, + cmder.playbackStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, hookEvent, eventResult -> { - if (eventResult.type == SipSubscribe.EventResultType.response) { - ResponseEvent responseEvent = (ResponseEvent) eventResult.event; - String contentString = new String(responseEvent.getResponse().getRawContent()); - // 鑾峰彇ssrc - int ssrcIndex = contentString.indexOf("y="); - // 妫�鏌ユ槸鍚︽湁y瀛楁 - if (ssrcIndex >= 0) { - //ssrc瑙勫畾闀垮害涓�10瀛楄妭锛屼笉鍙栦綑涓嬮暱搴︿互閬垮厤鍚庣画杩樻湁鈥渇=鈥濆瓧娈� TODO 鍚庣画瀵逛笉瑙勮寖鐨勯潪10浣峴src鍏煎 - String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); - // 鏌ヨ鍒皊src涓嶄竴鑷翠笖寮�鍚簡ssrc鏍¢獙鍒欓渶瑕侀拡瀵瑰鐞� - if (ssrcInfo.getSsrc().equals(ssrcInResponse)) { - return; - } - logger.info("[鍥炴斁娑堟伅] 鏀跺埌invite 200, 鍙戠幇涓嬬骇鑷畾涔変簡ssrc: {}", ssrcInResponse); - if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { - logger.info("[鍥炴斁娑堟伅] SSRC淇 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); - - if (!ssrcFactory.checkSsrc(mediaServerItem.getId(),ssrcInResponse)) { - // ssrc 涓嶅彲鐢� - // 閲婃斁ssrc - dynamicTask.stop(playBackTimeOutTaskKey); - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); - streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); - eventResult.msg = "涓嬬骇鑷畾涔変簡ssrc,浣嗘槸姝src涓嶅彲鐢�"; - eventResult.statusCode = 400; - errorEvent.response(eventResult); - return; - } - - // 鍗曠鍙fā寮弒treamId涔熸湁鍙樺寲锛岄渶瑕侀噸鏂拌缃洃鍚� - if (!mediaServerItem.isRtpEnable()) { - // 娣诲姞璁㈤槄 - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId()); - subscribe.removeSubscribe(hookSubscribe); - hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase()); - subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response) -> { - logger.info("[ZLM HOOK] ssrc淇鍚庢敹鍒拌闃呮秷鎭細 " + response.toJSONString()); - dynamicTask.stop(playBackTimeOutTaskKey); - // hook鍝嶅簲 - onPublishHandlerForPlayback(mediaServerItemInUse, response, device.getDeviceId(), channelId, playBackCallback); - hookEvent.call(new InviteStreamInfo(mediaServerItem, null, eventResult.callId, "rtp", ssrcInfo.getStream())); - }); - } - - // 鍏抽棴rtp server - mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream(), result->{ - if (result) { - // 閲嶆柊寮�鍚痵src server - mediaServerService.openRTPServer(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), true, ssrcInfo.getPort(), true, device.getStreamModeForParam()); - }else { - try { - logger.warn("[鍥炴斁娑堟伅]鍋滄 {}/{}", device.getDeviceId(), channelId); - cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null, null); - } catch (InvalidArgumentException | SipException | ParseException | SsrcTransactionNotFoundException e) { - logger.error("[鍛戒护鍙戦�佸け璐 鍋滄鐐规挱 鍋滄锛� 鍙戦�丅YE: {}", e.getMessage()); - throw new ControllerException(ErrorCode.ERROR100.getCode(), "鍛戒护鍙戦�佸け璐�: " + e.getMessage()); - } - - dynamicTask.stop(playBackTimeOutTaskKey); - // 閲婃斁ssrc - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); - streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); - errorEvent.response(eventResult); - eventResult.msg = "涓嬬骇鑷畾涔変簡ssrc,閲嶆柊璁剧疆鏀舵祦淇℃伅澶辫触"; - eventResult.statusCode = 500; - errorEvent.response(eventResult); - } - }); - } - } - } + // 澶勭悊鏀跺埌200ok鍚庣殑TCP涓诲姩杩炴帴浠ュ強SSRC涓嶄竴鑷寸殑闂 + InviteOKHandler(eventResult, ssrcInfo, mediaServerItem, device, channelId, + playBackTimeOutTaskKey, callback, inviteInfo, InviteSessionType.PLAYBACK); }, errorEvent); } catch (InvalidArgumentException | SipException | ParseException e) { - logger.error("[鍛戒护鍙戦�佸け璐 鍥炴斁: {}", e.getMessage()); + logger.error("[鍛戒护鍙戦�佸け璐 褰曞儚鍥炴斁: {}", e.getMessage()); SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(); eventResult.type = SipSubscribe.EventResultType.cmdSendFailEvent; @@ -656,44 +551,137 @@ } + private void InviteOKHandler(SipSubscribe.EventResult eventResult, SSRCInfo ssrcInfo, MediaServerItem mediaServerItem, + Device device, String channelId, String timeOutTaskKey, ErrorCallback<Object> callback, + InviteInfo inviteInfo, InviteSessionType inviteSessionType){ + inviteInfo.setStatus(InviteSessionStatus.ok); + ResponseEvent responseEvent = (ResponseEvent) eventResult.event; + String contentString = new String(responseEvent.getResponse().getRawContent()); + String ssrcInResponse = SipUtils.getSsrcFromSdp(contentString); + if (ssrcInfo.getSsrc().equals(ssrcInResponse)) { + // ssrc 涓�鑷� + if (mediaServerItem.isRtpEnable()) { + // 澶氱鍙� + if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE")) { + tcpActiveHandler(device, channelId, contentString, mediaServerItem, timeOutTaskKey, ssrcInfo, callback); + } + }else { + // 鍗曠鍙� + if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE")) { + logger.warn("[Invite 200OK] 鍗曠鍙f敹娴佹ā寮忎笉鏀寔tcp涓诲姩妯″紡鏀舵祦"); + } + + } + }else { + logger.info("[Invite 200OK] 鏀跺埌invite 200, 鍙戠幇涓嬬骇鑷畾涔変簡ssrc: {}", ssrcInResponse); + // ssrc 涓嶄竴鑷� + if (mediaServerItem.isRtpEnable()) { + // 澶氱鍙� + if (device.isSsrcCheck()) { + // ssrc妫�楠� + // 鏇存柊ssrc + logger.info("[Invite 200OK] SSRC淇 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); + // 閲婃斁ssrc + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); + Boolean result = mediaServerService.updateRtpServerSSRC(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse); + if (!result) { + try { + logger.warn("[Invite 200OK] 鏇存柊ssrc澶辫触锛屽仠姝㈢偣鎾� {}/{}", device.getDeviceId(), channelId); + cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null, null); + } catch (InvalidArgumentException | SipException | ParseException | SsrcTransactionNotFoundException e) { + logger.error("[鍛戒护鍙戦�佸け璐 鍋滄鎾斁锛� 鍙戦�丅YE: {}", e.getMessage()); + } + + dynamicTask.stop(timeOutTaskKey); + // 閲婃斁ssrc + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); + + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); + + callback.run(InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(), + "涓嬬骇鑷畾涔変簡ssrc,閲嶆柊璁剧疆鏀舵祦淇℃伅澶辫触", null); + inviteStreamService.call(inviteSessionType, device.getDeviceId(), channelId, null, + InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(), + "涓嬬骇鑷畾涔変簡ssrc,閲嶆柊璁剧疆鏀舵祦淇℃伅澶辫触", null); + + }else { + ssrcInfo.setSsrc(ssrcInResponse); + inviteInfo.setSsrcInfo(ssrcInfo); + inviteInfo.setStream(ssrcInfo.getStream()); + if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE")) { + if (mediaServerItem.isRtpEnable()) { + tcpActiveHandler(device, channelId, contentString, mediaServerItem, timeOutTaskKey, ssrcInfo, callback); + }else { + logger.warn("[Invite 200OK] 鍗曠鍙f敹娴佹ā寮忎笉鏀寔tcp涓诲姩妯″紡鏀舵祦"); + } + } + inviteStreamService.updateInviteInfo(inviteInfo); + } + } + }else { + if (ssrcInResponse != null) { + // 鍗曠鍙� + // 閲嶆柊璁㈤槄娴佷笂绾� + SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(inviteInfo.getDeviceId(), + inviteInfo.getChannelId(), null, inviteInfo.getStream()); + streamSession.remove(inviteInfo.getDeviceId(), + inviteInfo.getChannelId(), inviteInfo.getStream()); + inviteStreamService.updateInviteInfoForSSRC(inviteInfo, ssrcInResponse); + streamSession.put(device.getDeviceId(), channelId, ssrcTransaction.getCallId(), + inviteInfo.getStream(), ssrcInResponse, mediaServerItem.getId(), (SIPResponse) responseEvent.getResponse(), inviteSessionType); + } + } + } + } + + @Override - public void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback playBackCallback) { + public void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<Object> callback) { Device device = storager.queryVideoDevice(deviceId); if (device == null) { return; } MediaServerItem newMediaServerItem = getNewMediaServerItemHasAssist(device); if (newMediaServerItem == null) { - PlayBackResult<StreamInfo> downloadResult = new PlayBackResult<>(); - downloadResult.setCode(ErrorCode.ERROR100.getCode()); - downloadResult.setMsg("鏈壘鍒癮ssist鏈嶅姟"); - playBackCallback.call(downloadResult); + callback.run(InviteErrorCode.ERROR_FOR_ASSIST_NOT_READY.getCode(), + InviteErrorCode.ERROR_FOR_ASSIST_NOT_READY.getMsg(), + null); return; } + // 褰曞儚涓嬭浇涓嶄娇鐢ㄥ浐瀹氭祦鍦板潃锛屽浐瀹氭祦鍦板潃浼氬鑷村鏋滃紑濮嬫椂闂翠笌缁撴潫鏃堕棿涓�鑷存椂鏂囦欢閿欒鐨勫彔鍔犲湪涓�璧� SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, null, device.isSsrcCheck(), true, 0, false, device.getStreamModeForParam()); - download(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, downloadSpeed, infoCallBack, playBackCallback); + download(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, downloadSpeed, callback); } @Override - public void download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack) { + public void download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<Object> callback) { if (mediaServerItem == null || ssrcInfo == null) { + callback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(), + InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getMsg(), + null); return; } - Device device = storager.queryVideoDevice(deviceId); if (device == null) { - throw new ControllerException(ErrorCode.ERROR400.getCode(), "璁惧锛�" + deviceId + "涓嶅瓨鍦�"); + callback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(), + "璁惧锛�" + deviceId + "涓嶅瓨鍦�", + null); + return; } - PlayBackResult<StreamInfo> downloadResult = new PlayBackResult<>(); - logger.info("[褰曞儚涓嬭浇] deviceId: {}, channelId: {},鏀舵祦绔彛锛歿}, 鏀舵祦妯″紡锛歿}, SSRC: {}, SSRC鏍¢獙锛歿}", device.getDeviceId(), channelId, ssrcInfo.getPort(), device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); + logger.info("[褰曞儚涓嬭浇] deviceId: {}, channelId: {}, 涓嬭浇閫熷害锛歿}, 鏀舵祦绔彛锛歿}, 鏀舵祦妯″紡锛歿}, SSRC: {}, SSRC鏍¢獙锛歿}", device.getDeviceId(), channelId, downloadSpeed, ssrcInfo.getPort(), device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); + // 鍒濆鍖杛edis涓殑invite娑堟伅鐘舵�� + InviteInfo inviteInfo = InviteInfo.getInviteInfo(device.getDeviceId(), channelId, ssrcInfo.getStream(), ssrcInfo, + mediaServerItem.getSdpIp(), ssrcInfo.getPort(), device.getStreamMode(), InviteSessionType.DOWNLOAD, + InviteSessionStatus.ready); + inviteStreamService.updateInviteInfo(inviteInfo); String downLoadTimeOutTaskKey = UUID.randomUUID().toString(); dynamicTask.startDelay(downLoadTimeOutTaskKey, () -> { logger.warn(String.format("褰曞儚涓嬭浇璇锋眰瓒呮椂锛宒eviceId锛�%s 锛宑hannelId锛�%s", deviceId, channelId)); - downloadResult.setCode(ErrorCode.ERROR100.getCode()); - downloadResult.setMsg("褰曞儚涓嬭浇璇锋眰瓒呮椂"); - hookCallBack.call(downloadResult); + inviteStreamService.removeInviteInfo(inviteInfo); + callback.run(InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode(), + InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getMsg(), null); // 鐐规挱瓒呮椂鍥炲BYE 鍚屾椂閲婃斁ssrc浠ュ強姝ゆ鐐规挱鐨勮祫婧� try { @@ -709,100 +697,30 @@ SipSubscribe.Event errorEvent = event -> { dynamicTask.stop(downLoadTimeOutTaskKey); - downloadResult.setCode(ErrorCode.ERROR100.getCode()); - downloadResult.setMsg(String.format("褰曞儚涓嬭浇澶辫触锛� 閿欒鐮侊細 %s, %s", event.statusCode, event.msg)); - downloadResult.setEvent(event); - hookCallBack.call(downloadResult); + callback.run(InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode(), + String.format("褰曞儚涓嬭浇澶辫触锛� 閿欒鐮侊細 %s, %s", event.statusCode, event.msg), null); streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); + inviteStreamService.removeInviteInfo(inviteInfo); }; - InviteStreamCallback hookEvent = (InviteStreamInfo inviteStreamInfo) -> { - logger.info("[褰曞儚涓嬭浇]鏀跺埌璁㈤槄娑堟伅锛� " + inviteStreamInfo.getCallId()); + ZlmHttpHookSubscribe.Event hookEvent = (mediaServerItemInuse, hookParam) -> { + logger.info("[褰曞儚涓嬭浇]鏀跺埌璁㈤槄娑堟伅锛� " + hookParam); dynamicTask.stop(downLoadTimeOutTaskKey); - StreamInfo streamInfo = onPublishHandler(inviteStreamInfo.getMediaServerItem(), inviteStreamInfo.getResponse(), deviceId, channelId); - streamInfo.setStartTime(startTime); - streamInfo.setEndTime(endTime); - redisCatchStorage.startDownload(streamInfo, inviteStreamInfo.getCallId()); - downloadResult.setCode(ErrorCode.SUCCESS.getCode()); - downloadResult.setMsg(ErrorCode.SUCCESS.getMsg()); - downloadResult.setData(streamInfo); - downloadResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem()); - downloadResult.setResponse(inviteStreamInfo.getResponse()); - hookCallBack.call(downloadResult); + StreamInfo streamInfo = onPublishHandlerForDownload(mediaServerItemInuse, hookParam, deviceId, channelId, startTime, endTime); + if (streamInfo == null) { + logger.warn("[褰曞儚涓嬭浇] 鑾峰彇娴佸湴鍧�淇℃伅澶辫触"); + callback.run(InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), + InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null); + return; + } + callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo); + logger.info("[褰曞儚涓嬭浇] 璋冪敤鎴愬姛 deviceId: {}, channelId: {}, 寮�濮嬫椂闂�: {}, 缁撴潫鏃堕棿锛� {}", device.getDeviceId(), channelId, startTime, endTime); }; try { - cmder.downloadStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, infoCallBack, - hookEvent, errorEvent, eventResult -> - { - if (eventResult.type == SipSubscribe.EventResultType.response) { - ResponseEvent responseEvent = (ResponseEvent) eventResult.event; - String contentString = new String(responseEvent.getResponse().getRawContent()); - // 鑾峰彇ssrc - int ssrcIndex = contentString.indexOf("y="); - // 妫�鏌ユ槸鍚︽湁y瀛楁 - if (ssrcIndex >= 0) { - //ssrc瑙勫畾闀垮害涓�10瀛楄妭锛屼笉鍙栦綑涓嬮暱搴︿互閬垮厤鍚庣画杩樻湁鈥渇=鈥濆瓧娈� TODO 鍚庣画瀵逛笉瑙勮寖鐨勯潪10浣峴src鍏煎 - String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); - // 鏌ヨ鍒皊src涓嶄竴鑷翠笖寮�鍚簡ssrc鏍¢獙鍒欓渶瑕侀拡瀵瑰鐞� - if (ssrcInfo.getSsrc().equals(ssrcInResponse)) { - return; - } - logger.info("[褰曞儚涓嬭浇] 鏀跺埌invite 200, 鍙戠幇涓嬬骇鑷畾涔変簡ssrc: {}", ssrcInResponse); - if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { - logger.info("[褰曞儚涓嬭浇] SSRC淇 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); - - if (!ssrcFactory.checkSsrc(mediaServerItem.getId(),ssrcInResponse)) { - // ssrc 涓嶅彲鐢� - // 閲婃斁ssrc - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); - streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); - eventResult.msg = "涓嬬骇鑷畾涔変簡ssrc,浣嗘槸姝src涓嶅彲鐢�"; - eventResult.statusCode = 400; - errorEvent.response(eventResult); - return; - } - - // 鍗曠鍙fā寮弒treamId涔熸湁鍙樺寲锛岄渶瑕侀噸鏂拌缃洃鍚� - if (!mediaServerItem.isRtpEnable()) { - // 娣诲姞璁㈤槄 - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId()); - subscribe.removeSubscribe(hookSubscribe); - hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase()); - subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response) -> { - logger.info("[ZLM HOOK] ssrc淇鍚庢敹鍒拌闃呮秷鎭細 " + response.toJSONString()); - dynamicTask.stop(downLoadTimeOutTaskKey); - // hook鍝嶅簲 - onPublishHandlerForPlayback(mediaServerItemInUse, response, device.getDeviceId(), channelId, hookCallBack); - hookEvent.call(new InviteStreamInfo(mediaServerItem, null, eventResult.callId, "rtp", ssrcInfo.getStream())); - }); - } - - // 鍏抽棴rtp server - mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream(), result->{ - if (result) { - // 閲嶆柊寮�鍚痵src server - mediaServerService.openRTPServer(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), true, ssrcInfo.getPort(), true, device.getStreamModeForParam()); - }else { - try { - logger.warn("[褰曞儚涓嬭浇] 鍋滄{}/{}", device.getDeviceId(), channelId); - cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null, null); - } catch (InvalidArgumentException | SipException | ParseException | SsrcTransactionNotFoundException e) { - logger.error("[鍛戒护鍙戦�佸け璐 褰曞儚涓嬭浇鍋滄锛� 鍙戦�丅YE: {}", e.getMessage()); - throw new ControllerException(ErrorCode.ERROR100.getCode(), "鍛戒护鍙戦�佸け璐�: " + e.getMessage()); - } - - dynamicTask.stop(downLoadTimeOutTaskKey); - // 閲婃斁ssrc - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); - - streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); - eventResult.msg = "涓嬬骇鑷畾涔変簡ssrc,閲嶆柊璁剧疆鏀舵祦淇℃伅澶辫触"; - eventResult.statusCode = 500; - errorEvent.response(eventResult); - } - }); - } - } - } + cmder.downloadStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, + hookEvent, errorEvent, eventResult ->{ + // 澶勭悊鏀跺埌200ok鍚庣殑TCP涓诲姩杩炴帴浠ュ強SSRC涓嶄竴鑷寸殑闂 + InviteOKHandler(eventResult, ssrcInfo, mediaServerItem, device, channelId, + downLoadTimeOutTaskKey, callback, inviteInfo, InviteSessionType.DOWNLOAD); }); } catch (InvalidArgumentException | SipException | ParseException e) { logger.error("[鍛戒护鍙戦�佸け璐 褰曞儚涓嬭浇: {}", e.getMessage()); @@ -817,21 +735,22 @@ @Override public StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream) { - StreamInfo streamInfo = redisCatchStorage.queryDownload(deviceId, channelId, stream, null); - if (streamInfo != null) { - if (streamInfo.getProgress() == 1) { - return streamInfo; + InviteInfo inviteInfo = inviteStreamService.getInviteInfo(InviteSessionType.DOWNLOAD, deviceId, channelId, stream); + + if (inviteInfo != null && inviteInfo.getStreamInfo() != null) { + if (inviteInfo.getStreamInfo().getProgress() == 1) { + return inviteInfo.getStreamInfo(); } // 鑾峰彇褰撳墠宸蹭笅杞芥椂闀� - String mediaServerId = streamInfo.getMediaServerId(); + String mediaServerId = inviteInfo.getStreamInfo().getMediaServerId(); MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); if (mediaServerItem == null) { logger.warn("鏌ヨ褰曞儚淇℃伅鏃跺彂鐜拌妭鐐瑰凡绂荤嚎"); return null; } if (mediaServerItem.getRecordAssistPort() > 0) { - JSONObject jsonObject = assistRESTfulUtils.fileDuration(mediaServerItem, streamInfo.getApp(), streamInfo.getStream(), null); + JSONObject jsonObject = assistRESTfulUtils.fileDuration(mediaServerItem, inviteInfo.getStreamInfo().getApp(), inviteInfo.getStreamInfo().getStream(), null); if (jsonObject == null) { throw new ControllerException(ErrorCode.ERROR100.getCode(), "杩炴帴Assist鏈嶅姟澶辫触"); } @@ -839,10 +758,10 @@ long duration = jsonObject.getLong("data"); if (duration == 0) { - streamInfo.setProgress(0); + inviteInfo.getStreamInfo().setProgress(0); } else { - String startTime = streamInfo.getStartTime(); - String endTime = streamInfo.getEndTime(); + String startTime = inviteInfo.getStreamInfo().getStartTime(); + String endTime = inviteInfo.getStreamInfo().getEndTime(); long start = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime); long end = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime); @@ -850,40 +769,42 @@ BigDecimal totalCount = new BigDecimal(end - start); BigDecimal divide = currentCount.divide(totalCount, 2, RoundingMode.HALF_UP); double process = divide.doubleValue(); - streamInfo.setProgress(process); + inviteInfo.getStreamInfo().setProgress(process); } + inviteStreamService.updateInviteInfo(inviteInfo); } + } + return inviteInfo.getStreamInfo(); + } + return null; + } + + private StreamInfo onPublishHandlerForDownload(MediaServerItem mediaServerItemInuse, HookParam hookParam, String deviceId, String channelId, String startTime, String endTime) { + OnStreamChangedHookParam streamChangedHookParam = (OnStreamChangedHookParam) hookParam; + StreamInfo streamInfo = onPublishHandler(mediaServerItemInuse, streamChangedHookParam, deviceId, channelId); + if (streamInfo != null) { + streamInfo.setProgress(0); + streamInfo.setStartTime(startTime); + streamInfo.setEndTime(endTime); + InviteInfo inviteInfo = inviteStreamService.getInviteInfo(InviteSessionType.DOWNLOAD, deviceId, channelId, streamInfo.getStream()); + if (inviteInfo != null) { + logger.info("[褰曞儚涓嬭浇] 鏇存柊invite娑堟伅涓殑stream淇℃伅"); + inviteInfo.setStatus(InviteSessionStatus.ok); + inviteInfo.setStreamInfo(streamInfo); + inviteStreamService.updateInviteInfo(inviteInfo); } } return streamInfo; } - @Override - public void onPublishHandlerForDownload(InviteStreamInfo inviteStreamInfo, String deviceId, String channelId, String uuid) { - RequestMessage msg = new RequestMessage(); - msg.setKey(DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId); - msg.setId(uuid); - StreamInfo streamInfo = onPublishHandler(inviteStreamInfo.getMediaServerItem(), inviteStreamInfo.getResponse(), deviceId, channelId); - if (streamInfo != null) { - redisCatchStorage.startDownload(streamInfo, inviteStreamInfo.getCallId()); - msg.setData(JSON.toJSONString(streamInfo)); - resultHolder.invokeResult(msg); - } else { - logger.warn("璁惧棰勮API璋冪敤澶辫触锛�"); - msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), "璁惧棰勮API璋冪敤澶辫触锛�")); - resultHolder.invokeResult(msg); - } - } - - public StreamInfo onPublishHandler(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId) { - String streamId = resonse.getString("stream"); - JSONArray tracks = resonse.getJSONArray("tracks"); - StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem, "rtp", streamId, tracks, null); + public StreamInfo onPublishHandler(MediaServerItem mediaServerItem, OnStreamChangedHookParam hookParam, String deviceId, String channelId) { + StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem, "rtp", hookParam.getStream(), hookParam.getTracks(), null); streamInfo.setDeviceID(deviceId); streamInfo.setChannelId(channelId); return streamInfo; } + @Override public void zlmServerOffline(String mediaServerId) { @@ -976,15 +897,14 @@ @Override public void pauseRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException { - String key = redisCatchStorage.queryPlaybackForKey(null, null, streamId, null); - StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null); - if (null == streamInfo) { + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId); + if (null == inviteInfo || inviteInfo.getStreamInfo() == null) { logger.warn("streamId涓嶅瓨鍦�!"); throw new ServiceException("streamId涓嶅瓨鍦�"); } - streamInfo.setPause(true); - redisTemplate.opsForValue().set(key, streamInfo); - MediaServerItem mediaServerItem = mediaServerService.getOne(streamInfo.getMediaServerId()); + inviteInfo.getStreamInfo().setPause(true); + inviteStreamService.updateInviteInfo(inviteInfo); + MediaServerItem mediaServerItem = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId()); if (null == mediaServerItem) { logger.warn("mediaServer 涓嶅瓨鍦�!"); throw new ServiceException("mediaServer涓嶅瓨鍦�"); @@ -994,21 +914,20 @@ if (jsonObject == null || jsonObject.getInteger("code") != 0) { throw new ServiceException("鏆傚仠RTP鎺ユ敹澶辫触"); } - Device device = storager.queryVideoDevice(streamInfo.getDeviceID()); - cmder.playPauseCmd(device, streamInfo); + Device device = storager.queryVideoDevice(inviteInfo.getDeviceId()); + cmder.playPauseCmd(device, inviteInfo.getStreamInfo()); } @Override public void resumeRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException { - String key = redisCatchStorage.queryPlaybackForKey(null, null, streamId, null); - StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null); - if (null == streamInfo) { + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId); + if (null == inviteInfo || inviteInfo.getStreamInfo() == null) { logger.warn("streamId涓嶅瓨鍦�!"); throw new ServiceException("streamId涓嶅瓨鍦�"); } - streamInfo.setPause(false); - redisTemplate.opsForValue().set(key, streamInfo); - MediaServerItem mediaServerItem = mediaServerService.getOne(streamInfo.getMediaServerId()); + inviteInfo.getStreamInfo().setPause(false); + inviteStreamService.updateInviteInfo(inviteInfo); + MediaServerItem mediaServerItem = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId()); if (null == mediaServerItem) { logger.warn("mediaServer 涓嶅瓨鍦�!"); throw new ServiceException("mediaServer涓嶅瓨鍦�"); @@ -1018,7 +937,55 @@ if (jsonObject == null || jsonObject.getInteger("code") != 0) { throw new ServiceException("缁х画RTP鎺ユ敹澶辫触"); } - Device device = storager.queryVideoDevice(streamInfo.getDeviceID()); - cmder.playResumeCmd(device, streamInfo); + Device device = storager.queryVideoDevice(inviteInfo.getDeviceId()); + cmder.playResumeCmd(device, inviteInfo.getStreamInfo()); } + + @Override + public void getSnap(String deviceId, String channelId, String fileName, ErrorCallback errorCallback) { + Device device = deviceService.getDevice(deviceId); + if (device == null) { + errorCallback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(), InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getMsg(), null); + return; + } + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); + if (inviteInfo != null) { + if (inviteInfo.getStreamInfo() != null) { + // 宸插瓨鍦ㄧ嚎鐩存帴鎴浘 + MediaServerItem mediaServerItemInuse = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId()); + String streamUrl; + if (mediaServerItemInuse.getRtspPort() != 0) { + streamUrl = String.format("rtsp://127.0.0.1:%s/%s/%s", mediaServerItemInuse.getRtspPort(), "rtp", inviteInfo.getStreamInfo().getStream()); + }else { + streamUrl = String.format("http://127.0.0.1:%s/%s/%s.live.mp4", mediaServerItemInuse.getHttpPort(), "rtp", inviteInfo.getStreamInfo().getStream()); + } + String path = "snap"; + // 璇锋眰鎴浘 + logger.info("[璇锋眰鎴浘]: " + fileName); + zlmresTfulUtils.getSnap(mediaServerItemInuse, streamUrl, 15, 1, path, fileName); + File snapFile = new File(path + File.separator + fileName); + if (snapFile.exists()) { + errorCallback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), snapFile.getAbsoluteFile()); + }else { + errorCallback.run(InviteErrorCode.FAIL.getCode(), InviteErrorCode.FAIL.getMsg(), null); + } + return; + } + } + + MediaServerItem newMediaServerItem = getNewMediaServerItem(device); + 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) { + getSnap(deviceId, channelId, fileName, errorCallback); + }else { + errorCallback.run(InviteErrorCode.FAIL.getCode(), InviteErrorCode.FAIL.getMsg(), null); + } + }else { + errorCallback.run(InviteErrorCode.FAIL.getCode(), InviteErrorCode.FAIL.getMsg(), null); + } + }); + } + } -- Gitblit v1.8.0