From 764d04b497356ba6bcbb75fd42b51eca750f7223 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: 星期三, 29 五月 2024 15:02:51 +0800 Subject: [PATCH] 调整上级观看消息的发送 --- src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java | 313 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 276 insertions(+), 37 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java old mode 100644 new mode 100755 index 3e0297a..144fb59 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java @@ -1,62 +1,301 @@ package com.genersoft.iot.vmp.service.impl; -import com.alibaba.fastjson.JSONObject; -import com.genersoft.iot.vmp.common.StreamInfo; -import com.genersoft.iot.vmp.conf.MediaServerConfig; -import com.genersoft.iot.vmp.gb28181.bean.GbStream; -import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; +import com.genersoft.iot.vmp.common.InviteInfo; +import com.genersoft.iot.vmp.common.InviteSessionType; +import com.genersoft.iot.vmp.common.VideoManagerConstants; +import com.genersoft.iot.vmp.conf.UserSetting; +import com.genersoft.iot.vmp.conf.exception.ControllerException; +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; +import com.genersoft.iot.vmp.gb28181.bean.*; +import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; +import com.genersoft.iot.vmp.media.bean.MediaServer; +import com.genersoft.iot.vmp.media.bean.ResultForOnPublish; +import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; +import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; +import com.genersoft.iot.vmp.service.*; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; -import com.genersoft.iot.vmp.storager.IVideoManagerStorager; -import com.genersoft.iot.vmp.service.IMediaService; -import com.genersoft.iot.vmp.storager.dao.GbStreamMapper; +import com.genersoft.iot.vmp.storager.IVideoManagerStorage; +import com.genersoft.iot.vmp.utils.DateUtil; +import com.genersoft.iot.vmp.utils.MediaServerUtils; +import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; +import com.genersoft.iot.vmp.vmanager.bean.OtherPsSendInfo; +import com.genersoft.iot.vmp.vmanager.bean.OtherRtpSendInfo; +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 javax.sip.InvalidArgumentException; +import javax.sip.SipException; +import java.text.ParseException; +import java.util.List; +import java.util.Map; @Service public class MediaServiceImpl implements IMediaService { + + private final static Logger logger = LoggerFactory.getLogger(MediaServiceImpl.class); @Autowired private IRedisCatchStorage redisCatchStorage; @Autowired - private IVideoManagerStorager storager; + private IStreamProxyService streamProxyService; @Autowired - private ZLMRESTfulUtils zlmresTfulUtils; + private UserSetting userSetting; + @Autowired + private RedisTemplate<Object, Object> redisTemplate; + @Autowired + private IUserService userService; + + @Autowired + private IInviteStreamService inviteStreamService; + + @Autowired + private VideoStreamSessionManager sessionManager; + + @Autowired + private IVideoManagerStorage storager; + + @Autowired + private IDeviceService deviceService; + + @Autowired + private ISIPCommanderForPlatform commanderForPlatform; + + @Autowired + private ISIPCommander commander; @Override - public StreamInfo getStreamInfoByAppAndStream(String app, String stream) { - MediaServerConfig mediaInfo = redisCatchStorage.getMediaInfo(); - StreamInfo streamInfoResult = new StreamInfo(); - streamInfoResult.setStreamId(stream); - streamInfoResult.setApp(app); - streamInfoResult.setRtmp(String.format("rtmp://%s:%s/%s/%s", mediaInfo.getWanIp(), mediaInfo.getRtmpPort(), app, stream)); - streamInfoResult.setRtsp(String.format("rtsp://%s:%s/%s/%s", mediaInfo.getWanIp(), mediaInfo.getRtspPort(), app, stream)); - streamInfoResult.setFlv(String.format("http://%s:%s/%s/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream)); - streamInfoResult.setWs_flv(String.format("ws://%s:%s/%s/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream)); - streamInfoResult.setHls(String.format("http://%s:%s/%s/%s/hls.m3u8", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream)); - streamInfoResult.setWs_hls(String.format("ws://%s:%s/%s/%s/hls.m3u8", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream)); - streamInfoResult.setFmp4(String.format("http://%s:%s/%s/%s.live.mp4", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream)); - streamInfoResult.setWs_fmp4(String.format("ws://%s:%s/%s/%s.live.mp4", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream)); - streamInfoResult.setTs(String.format("http://%s:%s/%s/%s.live.ts", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream)); - streamInfoResult.setWs_ts(String.format("ws://%s:%s/%s/%s.live.ts", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream)); - streamInfoResult.setRtc(String.format("http://%s:%s/index/api/webrtc?app=%s&stream=%s&type=play", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream)); - - return streamInfoResult; - } - - @Override - public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream) { - StreamInfo streamInfo = null; - JSONObject mediaList = zlmresTfulUtils.getMediaList(app, stream); - if (mediaList != null) { - streamInfo = getStreamInfoByAppAndStream(app, stream); + public boolean authenticatePlay(String app, String stream, String callId) { + if (app == null || stream == null) { + return false; } - return streamInfo; + if ("rtp".equals(app)) { + return true; + } + StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(app, stream); + if (streamAuthorityInfo == null || streamAuthorityInfo.getCallId() == null) { + return true; + } + return streamAuthorityInfo.getCallId().equals(callId); } + @Override + public ResultForOnPublish authenticatePublish(MediaServer mediaServer, String app, String stream, String params) { + // 鎺ㄦ祦閴存潈鐨勫鐞� + if (!"rtp".equals(app)) { + StreamProxyItem streamProxyItem = streamProxyService.getStreamProxyByAppAndStream(app, stream); + if (streamProxyItem != null) { + ResultForOnPublish result = new ResultForOnPublish(); + result.setEnable_audio(streamProxyItem.isEnableAudio()); + result.setEnable_mp4(streamProxyItem.isEnableMp4()); + return result; + } + if (userSetting.getPushAuthority()) { + // 瀵逛簬鎺ㄦ祦杩涜閴存潈 + Map<String, String> paramMap = MediaServerUtils.urlParamToMap(params); + // 鎺ㄦ祦閴存潈 + if (params == null) { + logger.info("鎺ㄦ祦閴存潈澶辫触锛� 缂哄皯蹇呰鍙傛暟锛歴ign=md5(user琛ㄧ殑pushKey)"); + throw new ControllerException(ErrorCode.ERROR401.getCode(), "Unauthorized"); + } + + String sign = paramMap.get("sign"); + if (sign == null) { + logger.info("鎺ㄦ祦閴存潈澶辫触锛� 缂哄皯蹇呰鍙傛暟锛歴ign=md5(user琛ㄧ殑pushKey)"); + throw new ControllerException(ErrorCode.ERROR401.getCode(), "Unauthorized"); + } + // 鎺ㄦ祦鑷畾涔夋挱鏀鹃壌鏉冪爜 + String callId = paramMap.get("callId"); + // 閴存潈閰嶇疆 + boolean hasAuthority = userService.checkPushAuthority(callId, sign); + if (!hasAuthority) { + logger.info("鎺ㄦ祦閴存潈澶辫触锛� sign 鏃犳潈闄�: callId={}. sign={}", callId, sign); + throw new ControllerException(ErrorCode.ERROR401.getCode(), "Unauthorized"); + } + StreamAuthorityInfo streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(app, stream, mediaServer.getId()); + streamAuthorityInfo.setCallId(callId); + streamAuthorityInfo.setSign(sign); + // 閴存潈閫氳繃 + redisCatchStorage.updateStreamAuthorityInfo(app, stream, streamAuthorityInfo); + } + } + ResultForOnPublish result = new ResultForOnPublish(); + result.setEnable_audio(true); + + // 鏄惁褰曞儚 + if ("rtp".equals(app)) { + result.setEnable_mp4(userSetting.getRecordSip()); + } else { + result.setEnable_mp4(userSetting.isRecordPushLive()); + } + // 鍥芥爣娴� + if ("rtp".equals(app)) { + + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, stream); + + // 鍗曠鍙fā寮忎笅淇敼娴� ID + if (!mediaServer.isRtpEnable() && inviteInfo == null) { + String ssrc = String.format("%010d", Long.parseLong(stream, 16)); + inviteInfo = inviteStreamService.getInviteInfoBySSRC(ssrc); + if (inviteInfo != null) { + result.setStream_replace(inviteInfo.getStream()); + logger.info("[ZLM HOOK]鎺ㄦ祦閴存潈 stream: {} 鏇挎崲涓� {}", stream, inviteInfo.getStream()); + stream = inviteInfo.getStream(); + } + } + + // 璁剧疆闊抽淇℃伅鍙婂綍鍒朵俊鎭� + List<SsrcTransaction> ssrcTransactionForAll = sessionManager.getSsrcTransactionForAll(null, null, null, stream); + if (ssrcTransactionForAll != null && ssrcTransactionForAll.size() == 1) { + + // 涓哄綍鍒跺浗鏍囨ā鎷熶竴涓壌鏉冧俊鎭�, 鏂逛究鍚庣画鍐欏叆褰曞儚鏂囦欢鏃朵娇鐢� + StreamAuthorityInfo streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(app, stream, mediaServer.getId()); + streamAuthorityInfo.setApp(app); + streamAuthorityInfo.setStream(ssrcTransactionForAll.get(0).getStream()); + streamAuthorityInfo.setCallId(ssrcTransactionForAll.get(0).getSipTransactionInfo().getCallId()); + + redisCatchStorage.updateStreamAuthorityInfo(app, ssrcTransactionForAll.get(0).getStream(), streamAuthorityInfo); + + String deviceId = ssrcTransactionForAll.get(0).getDeviceId(); + String channelId = ssrcTransactionForAll.get(0).getChannelId(); + DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); + if (deviceChannel != null) { + result.setEnable_audio(deviceChannel.getHasAudio()); + } + // 濡傛灉鏄綍鍍忎笅杞藉氨璁剧疆瑙嗛闂撮殧鍗佺 + if (ssrcTransactionForAll.get(0).getType() == InviteSessionType.DOWNLOAD) { + // 鑾峰彇褰曞儚鐨勬�绘椂闀匡紝鐒跺悗璁剧疆涓鸿繖涓棰戠殑鏃堕暱 + InviteInfo inviteInfoForDownload = inviteStreamService.getInviteInfo(InviteSessionType.DOWNLOAD, deviceId, channelId, stream); + if (inviteInfoForDownload != null && inviteInfoForDownload.getStreamInfo() != null) { + String startTime = inviteInfoForDownload.getStreamInfo().getStartTime(); + String endTime = inviteInfoForDownload.getStreamInfo().getEndTime(); + long difference = DateUtil.getDifference(startTime, endTime) / 1000; + result.setMp4_max_second((int) difference); + result.setEnable_mp4(true); + // 璁剧疆涓�2淇濊瘉寰楀埌鐨刴p4鐨勬椂闀挎槸姝e父鐨� + result.setModify_stamp(2); + } + } + // 濡傛灉鏄痶alk瀵硅锛屽垯榛樿鑾峰彇澹伴煶 + if (ssrcTransactionForAll.get(0).getType() == InviteSessionType.TALK) { + result.setEnable_audio(true); + } + } + } else if (app.equals("broadcast")) { + result.setEnable_audio(true); + } else if (app.equals("talk")) { + result.setEnable_audio(true); + } + if (app.equalsIgnoreCase("rtp")) { + String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_" + stream; + OtherRtpSendInfo otherRtpSendInfo = (OtherRtpSendInfo) redisTemplate.opsForValue().get(receiveKey); + + String receiveKeyForPS = VideoManagerConstants.WVP_OTHER_RECEIVE_PS_INFO + userSetting.getServerId() + "_" + stream; + OtherPsSendInfo otherPsSendInfo = (OtherPsSendInfo) redisTemplate.opsForValue().get(receiveKeyForPS); + if (otherRtpSendInfo != null || otherPsSendInfo != null) { + result.setEnable_mp4(true); + } + } + return result; + } + + @Override + public boolean closeStreamOnNoneReader(String mediaServerId, String app, String stream, String schema) { + boolean result = false; + // 鍥芥爣绫诲瀷鐨勬祦 + if ("rtp".equals(app)) { + result = userSetting.getStreamOnDemand(); + // 鍥芥爣娴侊紝 鐐规挱/褰曞儚鍥炴斁/褰曞儚涓嬭浇 + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, stream); + // 鐐规挱 + if (inviteInfo != null) { + // 褰曞儚涓嬭浇 + if (inviteInfo.getType() == InviteSessionType.DOWNLOAD) { + return false; + } + // 鏀跺埌鏃犱汉瑙傜湅璇存槑娴佷篃娌℃湁鍦ㄥ線涓婄骇鎺ㄩ�� + if (redisCatchStorage.isChannelSendingRTP(inviteInfo.getChannelId())) { + List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByChannelId( + inviteInfo.getChannelId()); + if (!sendRtpItems.isEmpty()) { + for (SendRtpItem sendRtpItem : sendRtpItems) { + ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId()); + try { + commanderForPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId()); + } catch (SipException | InvalidArgumentException | ParseException e) { + logger.error("[鍛戒护鍙戦�佸け璐 鍥芥爣绾ц仈 鍙戦�丅YE: {}", e.getMessage()); + } + redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(), + sendRtpItem.getCallId(), sendRtpItem.getStream()); + if (InviteStreamType.PUSH == sendRtpItem.getPlayType()) { + redisCatchStorage.sendPlatformStopPlayMsg(sendRtpItem,parentPlatform); + } + } + } + } + Device device = deviceService.getDevice(inviteInfo.getDeviceId()); + if (device != null) { + try { + // 澶氭煡璇竴娆¢槻姝㈠凡缁忚澶勭悊浜� + InviteInfo info = inviteStreamService.getInviteInfo(inviteInfo.getType(), + inviteInfo.getDeviceId(), inviteInfo.getChannelId(), inviteInfo.getStream()); + if (info != null) { + commander.streamByeCmd(device, inviteInfo.getChannelId(), + inviteInfo.getStream(), null); + } else { + logger.info("[鏃犱汉瑙傜湅] 鏈壘鍒拌澶囩殑鐐规挱淇℃伅锛� {}锛� 娴侊細{}", inviteInfo.getDeviceId(), stream); + } + } catch (InvalidArgumentException | ParseException | SipException | + SsrcTransactionNotFoundException e) { + logger.error("[鏃犱汉瑙傜湅]鐐规挱锛� 鍙戦�丅YE澶辫触 {}", e.getMessage()); + } + } else { + logger.info("[鏃犱汉瑙傜湅] 鏈壘鍒拌澶囷細 {}锛屾祦锛歿}", inviteInfo.getDeviceId(), stream); + } + + inviteStreamService.removeInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId(), + inviteInfo.getChannelId(), inviteInfo.getStream()); + storager.stopPlay(inviteInfo.getDeviceId(), inviteInfo.getChannelId()); + return result; + } + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, stream, null); + if (sendRtpItem != null && "talk".equals(sendRtpItem.getApp())) { + return false; + } + } else if ("talk".equals(app) || "broadcast".equals(app)) { + return false; + } else { + // 闈炲浗鏍囨祦 鎺ㄦ祦/鎷夋祦浠g悊 + // 鎷夋祦浠g悊 + StreamProxyItem streamProxyItem = streamProxyService.getStreamProxyByAppAndStream(app, stream); + if (streamProxyItem != null) { + if (streamProxyItem.isEnableRemoveNoneReader()) { + // 鏃犱汉瑙傜湅鑷姩绉婚櫎 + result = true; + streamProxyService.del(app, stream); + String url = streamProxyItem.getUrl() != null ? streamProxyItem.getUrl() : streamProxyItem.getSrcUrl(); + logger.info("[{}/{}]<-[{}] 鎷夋祦浠g悊鏃犱汉瑙傜湅宸茬粡绉婚櫎", app, stream, url); + } else if (streamProxyItem.isEnableDisableNoneReader()) { + // 鏃犱汉瑙傜湅鍋滅敤 + result = true; + // 淇敼鏁版嵁 + streamProxyService.stop(app, stream); + } else { + // 鏃犱汉瑙傜湅涓嶅仛澶勭悊 + result = false; + } + } + } + return result; + } } -- Gitblit v1.8.0