From fa62ab9a0143433a5d058ab3229a37e4a9a0f696 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: 星期二, 20 六月 2023 14:16:46 +0800 Subject: [PATCH] Merge pull request #893 from sxh-netizen/wvp-28181-2.0 --- src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java | 390 +++++++++++++++++++++++++++++++++++++++---------------- 1 files changed, 276 insertions(+), 114 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 index 3907895..cebfa1d 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java @@ -18,7 +18,6 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 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.ZLMRTPServerFactory; @@ -116,28 +115,43 @@ @Override - public SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, ErrorCallback<Object> callback) { + public SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId,boolean isSubStream, ErrorCallback<Object> callback) { if (mediaServerItem == null) { throw new ControllerException(ErrorCode.ERROR100.getCode(), "鏈壘鍒板彲鐢ㄧ殑zlm"); } Device device = redisCatchStorage.getDevice(deviceId); - InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); - + InviteInfo inviteInfo; + if(device.isSwitchPrimarySubStream()){ + inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId,isSubStream); + }else { + inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); + } if (inviteInfo != null ) { if (inviteInfo.getStreamInfo() == null) { // 鐐规挱鍙戣捣浜嗕絾鏄皻鏈垚鍔�, 浠呮敞鍐屽洖璋冪瓑寰呯粨鏋滃嵆鍙� - inviteStreamService.once(InviteSessionType.PLAY, deviceId, channelId, null, callback); + if(device.isSwitchPrimarySubStream()){ + inviteStreamService.once(InviteSessionType.PLAY, deviceId, channelId,isSubStream, null, callback); + }else { + inviteStreamService.once(InviteSessionType.PLAY, deviceId, channelId, null, callback); + } 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); + if(device.isSwitchPrimarySubStream()){ + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream, null, + InviteErrorCode.ERROR_FOR_CATCH_DATA.getCode(), + "鐐规挱澶辫触锛� redis缂撳瓨streamId绛変簬null", + null); + }else { + 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(); @@ -146,41 +160,64 @@ Boolean ready = zlmrtpServerFactory.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); + if(device.isSwitchPrimarySubStream()){ + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream, null, + InviteErrorCode.SUCCESS.getCode(), + InviteErrorCode.SUCCESS.getMsg(), + streamInfo); + }else { + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, + InviteErrorCode.SUCCESS.getCode(), + InviteErrorCode.SUCCESS.getMsg(), + streamInfo); + } return inviteInfo.getSsrcInfo(); }else { // 鐐规挱鍙戣捣浜嗕絾鏄皻鏈垚鍔�, 浠呮敞鍐屽洖璋冪瓑寰呯粨鏋滃嵆鍙� - inviteStreamService.once(InviteSessionType.PLAY, deviceId, channelId, null, callback); - storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); - inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); + if(device.isSwitchPrimarySubStream()) { + inviteStreamService.once(InviteSessionType.PLAY, deviceId, channelId, null, callback); + storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); + inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); + }else { + inviteStreamService.once(InviteSessionType.PLAY, deviceId, channelId,isSubStream, null, callback); + inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId,isSubStream); + } } } } String streamId = null; if (mediaServerItem.isRtpEnable()) { - streamId = String.format("%s_%s", device.getDeviceId(), channelId); + if(device.isSwitchPrimarySubStream()){ + streamId = StreamInfo.getPlayStream(deviceId, channelId, isSubStream); + }else { + 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) { 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); + if(device.isSwitchPrimarySubStream()){ + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream, null, + InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), + InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getMsg(), + null); + }else { + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, + InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), + InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getMsg(), + null); + } return null; } // TODO 璁板綍鐐规挱鐨勭姸鎬� - play(mediaServerItem, ssrcInfo, device, channelId, callback); + play(mediaServerItem, ssrcInfo, device, channelId,isSubStream, callback); return ssrcInfo; } @Override - public void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, + public void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,boolean isSubStream, ErrorCallback<Object> callback) { if (mediaServerItem == null || ssrcInfo == null) { @@ -189,21 +226,11 @@ null); return; } - logger.info("\r\n" + - " [鐐规挱寮�濮媇 \r\n" + - "deviceId : {}, \r\n" + - "channelId : {},\r\n" + - "鏀舵祦绔彛 : {}, \r\n" + - "鏀舵祦妯″紡 : {}, \r\n" + - "SSRC : {}, \r\n" + - "SSRC鏍¢獙 锛歿}", - device.getDeviceId(), - channelId, - ssrcInfo.getPort(), - device.getStreamMode(), - ssrcInfo.getSsrc(), - device.isSsrcCheck()); - + if( device.isSwitchPrimarySubStream() ){ + logger.info("[鐐规挱寮�濮媇 deviceId: {}, channelId: {},鐮佹祦绫诲瀷锛歿},鏀舵祦绔彛锛� {}, 鏀舵祦妯″紡锛歿}, SSRC: {}, SSRC鏍¢獙锛歿}", device.getDeviceId(), channelId,isSubStream ? "杈呯爜娴�" : "涓荤爜娴�", ssrcInfo.getPort(), device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); + }else { + logger.info("[鐐规挱寮�濮媇 deviceId: {}, channelId: {},鏀舵祦绔彛锛� {}, 鏀舵祦妯″紡锛歿}, SSRC: {}, SSRC鏍¢獙锛歿}", device.getDeviceId(), channelId, ssrcInfo.getPort(), device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); + } //绔彛鑾峰彇澶辫触鐨剆srcInfo 娌℃湁蹇呰鍙戦�佺偣鎾寚浠� if (ssrcInfo.getPort() <= 0) { logger.info("[鐐规挱绔彛鍒嗛厤寮傚父]锛宒eviceId={},channelId={},ssrcInfo={}", device.getDeviceId(), channelId, ssrcInfo); @@ -212,23 +239,50 @@ 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); + if(device.isSwitchPrimarySubStream()){ + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream, null, + InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "鐐规挱绔彛鍒嗛厤寮傚父", null); + }else { + 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); - inviteStreamService.updateInviteInfo(inviteInfo); + InviteInfo inviteInfo; + + if(device.isSwitchPrimarySubStream()){ + // 鍒濆鍖杛edis涓殑invite娑堟伅鐘舵�� + inviteInfo = InviteInfo.getInviteInfo(device.getDeviceId(), channelId,isSubStream, ssrcInfo.getStream(), ssrcInfo, + mediaServerItem.getSdpIp(), ssrcInfo.getPort(), device.getStreamMode(), InviteSessionType.PLAY, + InviteSessionStatus.ready); + inviteStreamService.updateInviteInfoSub(inviteInfo); + }else { + // 鍒濆鍖杛edis涓殑invite娑堟伅鐘舵�� + inviteInfo = InviteInfo.getinviteInfo(device.getDeviceId(), channelId, ssrcInfo.getStream(), ssrcInfo, + mediaServerItem.getSdpIp(), ssrcInfo.getPort(), device.getStreamMode(), InviteSessionType.PLAY, + InviteSessionStatus.ready); + inviteStreamService.updateInviteInfo(inviteInfo); + } // 瓒呮椂澶勭悊 String timeOutTaskKey = UUID.randomUUID().toString(); dynamicTask.startDelay(timeOutTaskKey, () -> { // 鎵ц瓒呮椂浠诲姟鏃舵煡璇㈡槸鍚﹀凡缁忔垚鍔燂紝鎴愬姛浜嗗垯涓嶆墽琛岃秴鏃朵换鍔★紝闃叉瓒呮椂浠诲姟鍙栨秷澶辫触鐨勬儏鍐� - InviteInfo inviteInfoForTimeOut = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId); + InviteInfo inviteInfoForTimeOut; + if(device.isSwitchPrimarySubStream()){ + // 鍒濆鍖杛edis涓殑invite娑堟伅鐘舵�� + inviteInfoForTimeOut = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream); + }else { + // 鍒濆鍖杛edis涓殑invite娑堟伅鐘舵�� + inviteInfoForTimeOut = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId); + } if (inviteInfoForTimeOut == null || inviteInfoForTimeOut.getStreamInfo() == null) { - logger.info("[鐐规挱瓒呮椂] 鏀舵祦瓒呮椂 deviceId: {}, channelId: {}锛岀鍙o細{}, SSRC: {}", device.getDeviceId(), channelId, ssrcInfo.getPort(), ssrcInfo.getSsrc()); + if( device.isSwitchPrimarySubStream()){ + logger.info("[鐐规挱瓒呮椂] 鏀舵祦瓒呮椂 deviceId: {}, channelId: {},鐮佹祦绫诲瀷锛歿}锛岀鍙o細{}, SSRC: {}", device.getDeviceId(), channelId,isSubStream ? "杈呯爜娴�" : "涓荤爜娴�", ssrcInfo.getPort(), ssrcInfo.getSsrc()); + }else { + 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) { @@ -240,10 +294,16 @@ // // TODO 鍙戦�乧ancel // } 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); + if( device.isSwitchPrimarySubStream()){ + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream, null, + InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode(), InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getMsg(), null); + inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream); - inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId); + }else { + 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) { @@ -261,25 +321,42 @@ }, userSetting.getPlayTimeout()); try { - cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> { + cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId,isSubStream, (MediaServerItem mediaServerItemInuse, JSONObject response) -> { logger.info("鏀跺埌璁㈤槄娑堟伅锛� " + response.toJSONString()); dynamicTask.stop(timeOutTaskKey); // hook鍝嶅簲 - StreamInfo streamInfo = onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId); + StreamInfo streamInfo = onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId,isSubStream); 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); + if( device.isSwitchPrimarySubStream()){ + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream, null, + InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), + InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null); + }else { + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, + 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); - inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, - InviteErrorCode.SUCCESS.getCode(), - InviteErrorCode.SUCCESS.getMsg(), - streamInfo); - logger.info("[鐐规挱鎴愬姛] deviceId: {}, channelId: {}", device.getDeviceId(), channelId); + if( device.isSwitchPrimarySubStream()){ + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream, null, + InviteErrorCode.SUCCESS.getCode(), + InviteErrorCode.SUCCESS.getMsg(), + streamInfo); + }else { + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, + InviteErrorCode.SUCCESS.getCode(), + InviteErrorCode.SUCCESS.getMsg(), + streamInfo); + } + if( device.isSwitchPrimarySubStream() ){ + logger.info("[鐐规挱鎴愬姛] deviceId: {}, channelId: {},鐮佹祦绫诲瀷锛歿}", device.getDeviceId(), channelId,isSubStream ? "杈呯爜娴�" : "涓荤爜娴�"); + }else { + 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()); @@ -298,16 +375,17 @@ ResponseEvent responseEvent = (ResponseEvent) event.event; String contentString = new String(responseEvent.getResponse().getRawContent()); // 鑾峰彇ssrc - String ssrcInResponse = SipUtils.getSsrcFromSdp(contentString); - + int ssrcIndex = contentString.indexOf("y="); // 妫�鏌ユ槸鍚︽湁y瀛楁 - if (ssrcInResponse != null) { + 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 { - Gb28181Sdp gb28181Sdp = SipUtils.parseSDP(contentString); - SessionDescription sdp = gb28181Sdp.getBaseSdb(); + SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring); int port = -1; Vector mediaDescriptions = sdp.getMediaDescriptions(true); for (Object description : mediaDescriptions) { @@ -334,21 +412,24 @@ 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); + if(device.isSwitchPrimarySubStream()){ + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream, null, + InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(), + InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null); + }else { + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, + InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(), + InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null); + } } } return; } logger.info("[鐐规挱娑堟伅] 鏀跺埌invite 200, 鍙戠幇涓嬬骇鑷畾涔変簡ssrc: {}", ssrcInResponse); - if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { logger.info("[鐐规挱娑堟伅] SSRC淇 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); - // 閲婃斁ssrc mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); - // 鍗曠鍙fā寮弒treamId涔熸湁鍙樺寲锛岄噸鏂拌缃洃鍚嵆鍙� if (!mediaServerItem.isRtpEnable()) { // 娣诲姞璁㈤槄 @@ -361,21 +442,34 @@ logger.info("[ZLM HOOK] ssrc淇鍚庢敹鍒拌闃呮秷鎭細 " + response.toJSONString()); dynamicTask.stop(timeOutTaskKey); // hook鍝嶅簲 - StreamInfo streamInfo = onPublishHandlerForPlay(mediaServerItemInUse, response, device.getDeviceId(), channelId); + StreamInfo streamInfo = onPublishHandlerForPlay(mediaServerItemInUse, response, device.getDeviceId(), channelId,isSubStream); 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); + if( device.isSwitchPrimarySubStream()){ + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream, null, + InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), + InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null); + }else { + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, + 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); - inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, - InviteErrorCode.SUCCESS.getCode(), - InviteErrorCode.SUCCESS.getMsg(), - streamInfo); + if( device.isSwitchPrimarySubStream()){ + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream, null, + InviteErrorCode.SUCCESS.getCode(), + InviteErrorCode.SUCCESS.getMsg(), + streamInfo); + }else { + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, + InviteErrorCode.SUCCESS.getCode(), + InviteErrorCode.SUCCESS.getMsg(), + streamInfo); + } }); return; } @@ -391,14 +485,22 @@ } 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.PLAY, device.getDeviceId(), channelId, null, - InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(), - "涓嬬骇鑷畾涔変簡ssrc,閲嶆柊璁剧疆鏀舵祦淇℃伅澶辫触", null); + if( device.isSwitchPrimarySubStream()){ + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream, null, + InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(), + "涓嬬骇鑷畾涔変簡ssrc,閲嶆柊璁剧疆鏀舵祦淇℃伅澶辫触", null); + }else { + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, + InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(), + "涓嬬骇鑷畾涔変簡ssrc,閲嶆柊璁剧疆鏀舵祦淇℃伅澶辫触", null); + } }else { ssrcInfo.setSsrc(ssrcInResponse); @@ -409,7 +511,11 @@ logger.info("[鐐规挱娑堟伅] 鏀跺埌invite 200, 涓嬬骇鑷畾涔変簡ssrc, 浣嗘槸褰撳墠妯″紡鏃犻渶淇"); } } - inviteStreamService.updateInviteInfo(inviteInfo); + if(device.isSwitchPrimarySubStream()){ + inviteStreamService.updateInviteInfoSub(inviteInfo); + }else { + inviteStreamService.updateInviteInfo(inviteInfo); + } }, (event) -> { dynamicTask.stop(timeOutTaskKey); mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); @@ -420,11 +526,19 @@ 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); + if( device.isSwitchPrimarySubStream()){ + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream, null, + InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(), + String.format("鐐规挱澶辫触锛� 閿欒鐮侊細 %s, %s", event.statusCode, event.msg), null); - inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId); + inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream); + }else { + 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) { @@ -438,27 +552,51 @@ 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); + if( device.isSwitchPrimarySubStream()){ + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream, null, + InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getCode(), + InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getMsg(), null); - inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId); + inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId,isSubStream); + }else { + 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); + } } } - private StreamInfo onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId) { - StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId); + private StreamInfo onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId,boolean isSubStream) { + StreamInfo streamInfo = null; + Device device = redisCatchStorage.getDevice(deviceId); + if( device.isSwitchPrimarySubStream() ){ + streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId,isSubStream); + }else { + streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId); + } if (streamInfo != null) { - DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); - if (deviceChannel != null) { - deviceChannel.setStreamId(streamInfo.getStream()); - storager.startPlay(deviceId, channelId, streamInfo.getStream()); + InviteInfo inviteInfo; + if(device.isSwitchPrimarySubStream()){ + inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId,isSubStream); + }else { + DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); + if (deviceChannel != null) { + deviceChannel.setStreamId(streamInfo.getStream()); + storager.startPlay(deviceId, channelId, streamInfo.getStream()); + } + inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); } - InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); if (inviteInfo != null) { inviteInfo.setStatus(InviteSessionStatus.ok); inviteInfo.setStreamInfo(streamInfo); - inviteStreamService.updateInviteInfo(inviteInfo); + if(device.isSwitchPrimarySubStream()){ + inviteStreamService.updateInviteInfoSub(inviteInfo); + }else { + inviteStreamService.updateInviteInfo(inviteInfo); + } + } } return streamInfo; @@ -607,16 +745,17 @@ ResponseEvent responseEvent = (ResponseEvent) eventResult.event; String contentString = new String(responseEvent.getResponse().getRawContent()); // 鑾峰彇ssrc - String ssrcInResponse = SipUtils.getSsrcFromSdp(contentString); - + int ssrcIndex = contentString.indexOf("y="); // 妫�鏌ユ槸鍚︽湁y瀛楁 - if (ssrcInResponse != null) { + if (ssrcIndex >= 0) { + //ssrc瑙勫畾闀垮害涓�10瀛楄妭锛屼笉鍙栦綑涓嬮暱搴︿互閬垮厤鍚庣画杩樻湁鈥渇=鈥濆瓧娈� TODO 鍚庣画瀵逛笉瑙勮寖鐨勯潪10浣峴src鍏煎 + String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); // 鏌ヨ鍒皊src涓嶄竴鑷翠笖寮�鍚簡ssrc鏍¢獙鍒欓渶瑕侀拡瀵瑰鐞� if (ssrcInfo.getSsrc().equals(ssrcInResponse)) { if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE")) { + String substring = contentString.substring(0, contentString.indexOf("y=")); try { - Gb28181Sdp gb28181Sdp = SipUtils.parseSDP(contentString); - SessionDescription sdp = gb28181Sdp.getBaseSdb(); + SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring); int port = -1; Vector mediaDescriptions = sdp.getMediaDescriptions(true); for (Object description : mediaDescriptions) { @@ -684,6 +823,8 @@ } dynamicTask.stop(playBackTimeOutTaskKey); + // 閲婃斁ssrc + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); @@ -799,15 +940,17 @@ ResponseEvent responseEvent = (ResponseEvent) eventResult.event; String contentString = new String(responseEvent.getResponse().getRawContent()); // 鑾峰彇ssrc - String ssrcInResponse = SipUtils.getSsrcFromSdp(contentString); + int ssrcIndex = contentString.indexOf("y="); // 妫�鏌ユ槸鍚︽湁y瀛楁 - if (ssrcInResponse != null) { + if (ssrcIndex >= 0) { + //ssrc瑙勫畾闀垮害涓�10瀛楄妭锛屼笉鍙栦綑涓嬮暱搴︿互閬垮厤鍚庣画杩樻湁鈥渇=鈥濆瓧娈� TODO 鍚庣画瀵逛笉瑙勮寖鐨勯潪10浣峴src鍏煎 + String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); // 鏌ヨ鍒皊src涓嶄竴鑷翠笖寮�鍚簡ssrc鏍¢獙鍒欓渶瑕侀拡瀵瑰鐞� if (ssrcInfo.getSsrc().equals(ssrcInResponse)) { if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE")) { + String substring = contentString.substring(0, contentString.indexOf("y=")); try { - Gb28181Sdp gb28181Sdp = SipUtils.parseSDP(contentString); - SessionDescription sdp = gb28181Sdp.getBaseSdb(); + SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring); int port = -1; Vector mediaDescriptions = sdp.getMediaDescriptions(true); for (Object description : mediaDescriptions) { @@ -872,6 +1015,8 @@ } dynamicTask.stop(downLoadTimeOutTaskKey); + // 閲婃斁ssrc + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); @@ -971,6 +1116,7 @@ streamInfo.setChannelId(channelId); return streamInfo; } + @Override public void zlmServerOffline(String mediaServerId) { @@ -1108,14 +1254,18 @@ } @Override - public void getSnap(String deviceId, String channelId, String fileName, ErrorCallback errorCallback) { + public void getSnap(String deviceId, String channelId, String fileName,boolean isSubStream, 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); + InviteInfo inviteInfo; + if(device.isSwitchPrimarySubStream()){ + inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId,isSubStream); + }else { + inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); + } if (inviteInfo != null) { if (inviteInfo.getStreamInfo() != null) { // 宸插瓨鍦ㄧ嚎鐩存帴鎴浘 @@ -1130,10 +1280,9 @@ // 璇锋眰鎴浘 logger.info("[璇锋眰鎴浘]: " + fileName); zlmresTfulUtils.getSnap(mediaServerItemInuse, streamUrl, 15, 1, path, fileName); - String filePath = path + File.separator + fileName; File snapFile = new File(path + File.separator + fileName); if (snapFile.exists()) { - errorCallback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), filePath); + errorCallback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), snapFile.getAbsoluteFile()); }else { errorCallback.run(InviteErrorCode.FAIL.getCode(), InviteErrorCode.FAIL.getMsg(), null); } @@ -1142,11 +1291,11 @@ } MediaServerItem newMediaServerItem = getNewMediaServerItem(device); - play(newMediaServerItem, deviceId, channelId, (code, msg, data)->{ + play(newMediaServerItem, deviceId, channelId,isSubStream, (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); + getSnap(deviceId, channelId, fileName,isSubStream, errorCallback); }else { errorCallback.run(InviteErrorCode.FAIL.getCode(), InviteErrorCode.FAIL.getMsg(), null); } @@ -1156,4 +1305,17 @@ }); } + + /*======================璁惧涓诲瓙鐮佹祦閫昏緫START=========================*/ + public StreamInfo onPublishHandler(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId,boolean isSubStream) { + String streamId = resonse.getString("stream"); + JSONArray tracks = resonse.getJSONArray("tracks"); + StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem, "rtp", streamId, tracks, null); + streamInfo.setDeviceID(deviceId); + streamInfo.setChannelId(channelId); + streamInfo.setSubStream(isSubStream); + return streamInfo; + } + /*======================璁惧涓诲瓙鐮佹祦閫昏緫END=========================*/ + } -- Gitblit v1.8.0