From c1ac16bf620d09a94a0cfe184cbe1c9cb531a01b Mon Sep 17 00:00:00 2001
From: 648540858 <648540858@qq.com>
Date: 星期六, 23 三月 2024 15:38:54 +0800
Subject: [PATCH] 优化媒体节点服务的代码结构
---
src/main/java/com/genersoft/iot/vmp/media/abl/ABLHttpHookListener.java | 906 +++++++++++++++++++++++++++++++
src/main/java/com/genersoft/iot/vmp/media/abl/ABLRESTfulUtils.java | 403 +++++++++++++
src/main/java/com/genersoft/iot/vmp/media/abl/event/HookAblServerKeepaliveEvent.java | 24
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java | 17
src/main/java/com/genersoft/iot/vmp/media/abl/bean/AblServerConfig.java | 4
src/main/java/com/genersoft/iot/vmp/media/abl/ABLMediaServerStatusManger.java | 305 ++++++++++
src/main/java/com/genersoft/iot/vmp/media/abl/event/HookAblServerStartEvent.java | 24
7 files changed, 1,671 insertions(+), 12 deletions(-)
diff --git a/src/main/java/com/genersoft/iot/vmp/media/abl/ABLHttpHookListener.java b/src/main/java/com/genersoft/iot/vmp/media/abl/ABLHttpHookListener.java
new file mode 100755
index 0000000..026134a
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/media/abl/ABLHttpHookListener.java
@@ -0,0 +1,906 @@
+package com.genersoft.iot.vmp.media.abl;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.genersoft.iot.vmp.common.InviteInfo;
+import com.genersoft.iot.vmp.common.InviteSessionType;
+import com.genersoft.iot.vmp.common.StreamInfo;
+import com.genersoft.iot.vmp.common.VideoManagerConstants;
+import com.genersoft.iot.vmp.conf.UserSetting;
+import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
+import com.genersoft.iot.vmp.gb28181.bean.*;
+import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
+import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
+import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager;
+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.ISIPCommanderForPlatform;
+import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
+import com.genersoft.iot.vmp.media.abl.event.HookAblServerKeepaliveEvent;
+import com.genersoft.iot.vmp.media.bean.MediaInfo;
+import com.genersoft.iot.vmp.media.service.IMediaServerService;
+import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager;
+import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
+import com.genersoft.iot.vmp.media.zlm.dto.*;
+import com.genersoft.iot.vmp.media.zlm.dto.hook.*;
+import com.genersoft.iot.vmp.media.zlm.event.HookZlmServerStartEvent;
+import com.genersoft.iot.vmp.service.*;
+import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
+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.OtherPsSendInfo;
+import com.genersoft.iot.vmp.vmanager.bean.OtherRtpSendInfo;
+import com.genersoft.iot.vmp.vmanager.bean.StreamContent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.util.ObjectUtils;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.context.request.async.DeferredResult;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.sip.InvalidArgumentException;
+import javax.sip.SipException;
+import java.text.ParseException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * ABL鏈嶅姟Hook浜嬩欢
+ */
+@RestController
+@RequestMapping("/index/hook")
+public class ABLHttpHookListener {
+
+ private final static Logger logger = LoggerFactory.getLogger(ABLHttpHookListener.class);
+
+ @Autowired
+ private SIPCommander cmder;
+
+ @Autowired
+ private ISIPCommanderForPlatform commanderFroPlatform;
+
+ @Autowired
+ private AudioBroadcastManager audioBroadcastManager;
+
+ @Autowired
+ private IPlayService playService;
+
+ @Autowired
+ private IVideoManagerStorage storager;
+
+ @Autowired
+ private IRedisCatchStorage redisCatchStorage;
+
+ @Autowired
+ private IInviteStreamService inviteStreamService;
+
+ @Autowired
+ private IDeviceService deviceService;
+
+ @Autowired
+ private IMediaServerService mediaServerService;
+
+ @Autowired
+ private IStreamProxyService streamProxyService;
+
+ @Autowired
+ private DeferredResultHolder resultHolder;
+
+ @Autowired
+ private IMediaService mediaService;
+
+ @Autowired
+ private EventPublisher eventPublisher;
+
+ @Autowired
+ private ZLMMediaListManager zlmMediaListManager;
+
+ @Autowired
+ private ZlmHttpHookSubscribe subscribe;
+
+ @Autowired
+ private UserSetting userSetting;
+
+ @Autowired
+ private IUserService userService;
+
+ @Autowired
+ private ICloudRecordService cloudRecordService;
+
+ @Autowired
+ private VideoStreamSessionManager sessionManager;
+
+ @Autowired
+ private SSRCFactory ssrcFactory;
+
+ @Qualifier("taskExecutor")
+ @Autowired
+ private ThreadPoolTaskExecutor taskExecutor;
+
+ @Autowired
+ private RedisTemplate<Object, Object> redisTemplate;
+
+ @Autowired
+ private ApplicationEventPublisher applicationEventPublisher;
+
+ /**
+ * 鏈嶅姟鍣ㄥ畾鏃朵笂鎶ユ椂闂达紝涓婃姤闂撮殧鍙厤缃紝榛樿10s涓婃姤涓�娆�
+ */
+ @ResponseBody
+
+ @PostMapping(value = "/on_server_keepalive", produces = "application/json;charset=UTF-8")
+ public HookResult onServerKeepalive(@RequestBody OnServerKeepaliveHookParam param) {
+ try {
+ HookAblServerKeepaliveEvent event = new HookAblServerKeepaliveEvent(this);
+ MediaServer mediaServerItem = mediaServerService.getOne(param.getMediaServerId());
+ if (mediaServerItem != null) {
+ event.setMediaServerItem(mediaServerItem);
+ applicationEventPublisher.publishEvent(event);
+ }
+ }catch (Exception e) {
+ logger.info("[ZLM-HOOK-蹇冭烦] 鍙戦�侀�氱煡澶辫触 ", e);
+ }
+ return HookResult.SUCCESS();
+ }
+
+ /**
+ * 鎾斁鍣ㄩ壌鏉冧簨浠讹紝rtsp/rtmp/http-flv/ws-flv/hls鐨勬挱鏀鹃兘灏嗚Е鍙戞閴存潈浜嬩欢銆�
+ */
+ @ResponseBody
+ @PostMapping(value = "/on_play", produces = "application/json;charset=UTF-8")
+ public HookResult onPlay(@RequestBody OnPlayHookParam param) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("[ZLM HOOK] 鎾斁閴存潈锛歿}->{}", param.getMediaServerId(), param);
+ }
+ String mediaServerId = param.getMediaServerId();
+
+ taskExecutor.execute(() -> {
+ JSONObject json = (JSONObject) JSON.toJSON(param);
+ ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_play, json);
+ if (subscribe != null) {
+ MediaServer mediaInfo = mediaServerService.getOne(mediaServerId);
+ if (mediaInfo != null) {
+ subscribe.response(mediaInfo, param);
+ }
+ }
+ });
+ if (!"rtp".equals(param.getApp())) {
+ Map<String, String> paramMap = urlParamToMap(param.getParams());
+ StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream());
+ if (streamAuthorityInfo != null && streamAuthorityInfo.getCallId() != null && !streamAuthorityInfo.getCallId().equals(paramMap.get("callId"))) {
+ return new HookResult(401, "Unauthorized");
+ }
+ }
+
+ return HookResult.SUCCESS();
+ }
+
+ /**
+ * rtsp/rtmp/rtp鎺ㄦ祦閴存潈浜嬩欢銆�
+ */
+ @ResponseBody
+ @PostMapping(value = "/on_publish", produces = "application/json;charset=UTF-8")
+ public HookResultForOnPublish onPublish(@RequestBody OnPublishHookParam param) {
+
+ JSONObject json = (JSONObject) JSON.toJSON(param);
+
+ logger.info("[ABL HOOK]鎺ㄦ祦閴存潈锛歿}->{}", param.getMediaServerId(), param);
+ // TODO 鍔犲揩澶勭悊閫熷害
+
+ String mediaServerId = json.getString("mediaServerId");
+ MediaServer mediaInfo = mediaServerService.getOne(mediaServerId);
+ if (mediaInfo == null) {
+ return new HookResultForOnPublish(200, "success");
+ }
+ // 鎺ㄦ祦閴存潈鐨勫鐞�
+ if (!"rtp".equals(param.getApp())) {
+ StreamProxyItem stream = streamProxyService.getStreamProxyByAppAndStream(param.getApp(), param.getStream());
+ if (stream != null) {
+ HookResultForOnPublish result = HookResultForOnPublish.SUCCESS();
+ result.setEnable_audio(stream.isEnableAudio());
+ result.setEnable_mp4(stream.isEnableMp4());
+ return result;
+ }
+ if (userSetting.getPushAuthority()) {
+ // 鎺ㄦ祦閴存潈
+ if (param.getParams() == null) {
+ logger.info("鎺ㄦ祦閴存潈澶辫触锛� 缂哄皯蹇呰鍙傛暟锛歴ign=md5(user琛ㄧ殑pushKey)");
+ return new HookResultForOnPublish(401, "Unauthorized");
+ }
+ Map<String, String> paramMap = urlParamToMap(param.getParams());
+ String sign = paramMap.get("sign");
+ if (sign == null) {
+ logger.info("鎺ㄦ祦閴存潈澶辫触锛� 缂哄皯蹇呰鍙傛暟锛歴ign=md5(user琛ㄧ殑pushKey)");
+ return new HookResultForOnPublish(401, "Unauthorized");
+ }
+ // 鎺ㄦ祦鑷畾涔夋挱鏀鹃壌鏉冪爜
+ String callId = paramMap.get("callId");
+ // 閴存潈閰嶇疆
+ boolean hasAuthority = userService.checkPushAuthority(callId, sign);
+ if (!hasAuthority) {
+ logger.info("鎺ㄦ祦閴存潈澶辫触锛� sign 鏃犳潈闄�: callId={}. sign={}", callId, sign);
+ return new HookResultForOnPublish(401, "Unauthorized");
+ }
+ StreamAuthorityInfo streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(param);
+ streamAuthorityInfo.setCallId(callId);
+ streamAuthorityInfo.setSign(sign);
+ // 閴存潈閫氳繃
+ redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), param.getStream(), streamAuthorityInfo);
+ }
+ } else {
+ zlmMediaListManager.sendStreamEvent(param.getApp(), param.getStream(), param.getMediaServerId());
+ }
+
+
+ HookResultForOnPublish result = HookResultForOnPublish.SUCCESS();
+ result.setEnable_audio(true);
+ taskExecutor.execute(() -> {
+ ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_publish, json);
+ if (subscribe != null) {
+ subscribe.response(mediaInfo, param);
+ }
+ });
+
+ // 鏄惁褰曞儚
+ if ("rtp".equals(param.getApp())) {
+ result.setEnable_mp4(userSetting.getRecordSip());
+ } else {
+ result.setEnable_mp4(userSetting.isRecordPushLive());
+ }
+ // 鍥芥爣娴�
+ if ("rtp".equals(param.getApp())) {
+
+ InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, param.getStream());
+
+ // 鍗曠鍙fā寮忎笅淇敼娴� ID
+ if (!mediaInfo.isRtpEnable() && inviteInfo == null) {
+ String ssrc = String.format("%010d", Long.parseLong(param.getStream(), 16));
+ inviteInfo = inviteStreamService.getInviteInfoBySSRC(ssrc);
+ if (inviteInfo != null) {
+ result.setStream_replace(inviteInfo.getStream());
+ logger.info("[ABL HOOK]鎺ㄦ祦閴存潈 stream: {} 鏇挎崲涓� {}", param.getStream(), inviteInfo.getStream());
+ }
+ }
+
+ // 璁剧疆闊抽淇℃伅鍙婂綍鍒朵俊鎭�
+ List<SsrcTransaction> ssrcTransactionForAll = sessionManager.getSsrcTransactionForAll(null, null, null, param.getStream());
+ if (ssrcTransactionForAll != null && ssrcTransactionForAll.size() == 1) {
+
+ // 涓哄綍鍒跺浗鏍囨ā鎷熶竴涓壌鏉冧俊鎭�, 鏂逛究鍚庣画鍐欏叆褰曞儚鏂囦欢鏃朵娇鐢�
+ StreamAuthorityInfo streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(param);
+ streamAuthorityInfo.setApp(param.getApp());
+ streamAuthorityInfo.setStream(ssrcTransactionForAll.get(0).getStream());
+ streamAuthorityInfo.setCallId(ssrcTransactionForAll.get(0).getSipTransactionInfo().getCallId());
+
+ redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), 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.isHasAudio());
+ }
+ // 濡傛灉鏄綍鍍忎笅杞藉氨璁剧疆瑙嗛闂撮殧鍗佺
+ if (ssrcTransactionForAll.get(0).getType() == InviteSessionType.DOWNLOAD) {
+ // 鑾峰彇褰曞儚鐨勬�绘椂闀匡紝鐒跺悗璁剧疆涓鸿繖涓棰戠殑鏃堕暱
+ InviteInfo inviteInfoForDownload = inviteStreamService.getInviteInfo(InviteSessionType.DOWNLOAD, deviceId, channelId, param.getStream());
+ 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 (param.getApp().equals("broadcast")) {
+ result.setEnable_audio(true);
+ } else if (param.getApp().equals("talk")) {
+ result.setEnable_audio(true);
+ }
+ if (param.getApp().equalsIgnoreCase("rtp")) {
+ String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_" + param.getStream();
+ OtherRtpSendInfo otherRtpSendInfo = (OtherRtpSendInfo) redisTemplate.opsForValue().get(receiveKey);
+
+ String receiveKeyForPS = VideoManagerConstants.WVP_OTHER_RECEIVE_PS_INFO + userSetting.getServerId() + "_" + param.getStream();
+ OtherPsSendInfo otherPsSendInfo = (OtherPsSendInfo) redisTemplate.opsForValue().get(receiveKeyForPS);
+ if (otherRtpSendInfo != null || otherPsSendInfo != null) {
+ result.setEnable_mp4(true);
+ }
+ }
+ logger.info("[ABL HOOK]鎺ㄦ祦閴存潈 鍝嶅簲锛歿}->{}->>>>{}", param.getMediaServerId(), param, result);
+ return result;
+ }
+
+
+ /**
+ * rtsp/rtmp娴佹敞鍐屾垨娉ㄩ攢鏃惰Е鍙戞浜嬩欢锛涙浜嬩欢瀵瑰洖澶嶄笉鏁忔劅銆�
+ */
+ @ResponseBody
+ @PostMapping(value = "/on_stream_changed", produces = "application/json;charset=UTF-8")
+ public HookResult onStreamChanged(@RequestBody OnStreamChangedHookParam param) {
+
+ if (param.isRegist()) {
+ logger.info("[ABL HOOK] 娴佹敞鍐�, {}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream());
+ } else {
+ logger.info("[ABL HOOK] 娴佹敞閿�, {}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream());
+ }
+
+ JSONObject json = (JSONObject) JSON.toJSON(param);
+ taskExecutor.execute(() -> {
+ ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_stream_changed, json);
+ MediaServer mediaInfo = mediaServerService.getOne(param.getMediaServerId());
+ if (mediaInfo == null) {
+ logger.info("[ABL HOOK] 娴佸彉鍖栨湭鎵惧埌ABL, {}", param.getMediaServerId());
+ return;
+ }
+ if (subscribe != null) {
+ subscribe.response(mediaInfo, param);
+ }
+
+ // TODO 閲嶆瀯姝ゅ閫昏緫
+ if (param.isRegist()) {
+ // 澶勭悊娴佹敞鍐岀殑閴存潈淇℃伅锛� 娴佹敞閿�杩欓噷涓嶅啀鍒犻櫎閴存潈淇℃伅锛屼笅娆℃潵浜嗘柊鐨勯壌鏉冧俊鎭細瀵瑰氨鐨勮繘琛岃鐩�
+ if (param.getOriginType() == OriginType.RTMP_PUSH.ordinal()
+ || param.getOriginType() == OriginType.RTSP_PUSH.ordinal()
+ || param.getOriginType() == OriginType.RTC_PUSH.ordinal()) {
+ StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream());
+ if (streamAuthorityInfo == null) {
+ streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(param);
+ } else {
+ streamAuthorityInfo.setOriginType(param.getOriginType());
+ streamAuthorityInfo.setOriginTypeStr(param.getOriginTypeStr());
+ }
+ redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), param.getStream(), streamAuthorityInfo);
+ }
+ }
+ if ("rtsp".equals(param.getSchema())) {
+ logger.info("娴佸彉鍖栵細娉ㄥ唽->{}, app->{}, stream->{}", param.isRegist(), param.getApp(), param.getStream());
+ if (param.isRegist()) {
+ mediaServerService.addCount(param.getMediaServerId());
+ } else {
+ mediaServerService.removeCount(param.getMediaServerId());
+ }
+
+ int updateStatusResult = streamProxyService.updateStatus(param.isRegist(), param.getApp(), param.getStream());
+ if (updateStatusResult > 0) {
+
+ }
+
+ if ("rtp".equals(param.getApp()) && !param.isRegist()) {
+ InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, param.getStream());
+ if (inviteInfo != null && (inviteInfo.getType() == InviteSessionType.PLAY || inviteInfo.getType() == InviteSessionType.PLAYBACK)) {
+ inviteStreamService.removeInviteInfo(inviteInfo);
+ storager.stopPlay(inviteInfo.getDeviceId(), inviteInfo.getChannelId());
+ }
+ } else if ("broadcast".equals(param.getApp())) {
+ // 璇煶瀵硅鎺ㄦ祦 stream闇�瑕佹弧瓒虫牸寮廳eviceId_channelId
+ if (param.getStream().indexOf("_") > 0) {
+ String[] streamArray = param.getStream().split("_");
+ if (streamArray.length == 2) {
+ String deviceId = streamArray[0];
+ String channelId = streamArray[1];
+ Device device = deviceService.getDevice(deviceId);
+ if (device != null) {
+ if (param.isRegist()) {
+ if (audioBroadcastManager.exit(deviceId, channelId)) {
+ playService.stopAudioBroadcast(deviceId, channelId);
+ }
+ // 寮�鍚闊冲璁查�氶亾
+ try {
+ playService.audioBroadcastCmd(device, channelId, mediaInfo, param.getApp(), param.getStream(), 60, false, (msg) -> {
+ logger.info("[璇煶瀵硅] 閫氶亾寤虹珛鎴愬姛, device: {}, channel: {}", deviceId, channelId);
+ });
+ } catch (InvalidArgumentException | ParseException | SipException e) {
+ logger.error("[鍛戒护鍙戦�佸け璐 璇煶瀵硅: {}", e.getMessage());
+ }
+ } else {
+ // 娴佹敞閿�
+ playService.stopAudioBroadcast(deviceId, channelId);
+ }
+ } else {
+ logger.info("[璇煶瀵硅] 鏈壘鍒拌澶囷細{}", deviceId);
+ }
+ }
+ }
+ } else if ("talk".equals(param.getApp())) {
+ // 璇煶瀵硅鎺ㄦ祦 stream闇�瑕佹弧瓒虫牸寮廳eviceId_channelId
+ if (param.getStream().indexOf("_") > 0) {
+ String[] streamArray = param.getStream().split("_");
+ if (streamArray.length == 2) {
+ String deviceId = streamArray[0];
+ String channelId = streamArray[1];
+ Device device = deviceService.getDevice(deviceId);
+ if (device != null) {
+ if (param.isRegist()) {
+ if (audioBroadcastManager.exit(deviceId, channelId)) {
+ playService.stopAudioBroadcast(deviceId, channelId);
+ }
+ // 寮�鍚闊冲璁查�氶亾
+ playService.talkCmd(device, channelId, mediaInfo, param.getStream(), (msg) -> {
+ logger.info("[璇煶瀵硅] 閫氶亾寤虹珛鎴愬姛, device: {}, channel: {}", deviceId, channelId);
+ });
+ } else {
+ // 娴佹敞閿�
+ playService.stopTalk(device, channelId, param.isRegist());
+ }
+ } else {
+ logger.info("[璇煶瀵硅] 鏈壘鍒拌澶囷細{}", deviceId);
+ }
+ }
+ }
+
+ } else {
+ if (!"rtp".equals(param.getApp())) {
+ String type = OriginType.values()[param.getOriginType()].getType();
+ if (param.isRegist()) {
+ StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(
+ param.getApp(), param.getStream());
+ String callId = null;
+ if (streamAuthorityInfo != null) {
+ callId = streamAuthorityInfo.getCallId();
+ }
+ StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaInfo,
+ param.getApp(), param.getStream(), MediaInfo.getInstance(param), callId);
+ param.setStreamInfo(new StreamContent(streamInfoByAppAndStream));
+ redisCatchStorage.addStream(mediaInfo, type, param.getApp(), param.getStream(), param);
+ if (param.getOriginType() == OriginType.RTSP_PUSH.ordinal()
+ || param.getOriginType() == OriginType.RTMP_PUSH.ordinal()
+ || param.getOriginType() == OriginType.RTC_PUSH.ordinal()) {
+ param.setSeverId(userSetting.getServerId());
+ zlmMediaListManager.addPush(param);
+
+ // 鍐椾綑鏁版嵁锛岃嚜宸辩郴缁熶腑鑷敤
+ redisCatchStorage.addPushListItem(param.getApp(), param.getStream(), param);
+ }
+ } else {
+ // 鍏煎娴佹敞閿�鏃剁被鍨嬩粠redis璁板綍鑾峰彇
+ OnStreamChangedHookParam onStreamChangedHookParam = redisCatchStorage.getStreamInfo(
+ param.getApp(), param.getStream(), param.getMediaServerId());
+ if (onStreamChangedHookParam != null) {
+ type = OriginType.values()[onStreamChangedHookParam.getOriginType()].getType();
+ redisCatchStorage.removeStream(mediaInfo.getId(), type, param.getApp(), param.getStream());
+ if ("PUSH".equalsIgnoreCase(type)) {
+ // 鍐椾綑鏁版嵁锛岃嚜宸辩郴缁熶腑鑷敤
+ redisCatchStorage.removePushListItem(param.getApp(), param.getStream(), param.getMediaServerId());
+ }
+ }
+ GbStream gbStream = storager.getGbStream(param.getApp(), param.getStream());
+ if (gbStream != null) {
+// eventPublisher.catalogEventPublishForStream(null, gbStream, CatalogEvent.OFF);
+ }
+ zlmMediaListManager.removeMedia(param.getApp(), param.getStream());
+ }
+ GbStream gbStream = storager.getGbStream(param.getApp(), param.getStream());
+ if (gbStream != null) {
+ if (userSetting.isUsePushingAsStatus()) {
+ eventPublisher.catalogEventPublishForStream(null, gbStream, param.isRegist() ? CatalogEvent.ON : CatalogEvent.OFF);
+ }
+ }
+ if (type != null) {
+ // 鍙戦�佹祦鍙樺寲redis娑堟伅
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("serverId", userSetting.getServerId());
+ jsonObject.put("app", param.getApp());
+ jsonObject.put("stream", param.getStream());
+ jsonObject.put("register", param.isRegist());
+ jsonObject.put("mediaServerId", param.getMediaServerId());
+ redisCatchStorage.sendStreamChangeMsg(type, jsonObject);
+ }
+ }
+ }
+ if (!param.isRegist()) {
+ List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByStream(param.getStream());
+ if (!sendRtpItems.isEmpty()) {
+ for (SendRtpItem sendRtpItem : sendRtpItems) {
+ if (sendRtpItem != null && sendRtpItem.getApp().equals(param.getApp())) {
+ String platformId = sendRtpItem.getPlatformId();
+ ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId);
+ Device device = deviceService.getDevice(platformId);
+
+ try {
+ if (platform != null) {
+ commanderFroPlatform.streamByeCmd(platform, sendRtpItem);
+ redisCatchStorage.deleteSendRTPServer(platformId, sendRtpItem.getChannelId(),
+ sendRtpItem.getCallId(), sendRtpItem.getStream());
+ } else {
+ cmder.streamByeCmd(device, sendRtpItem.getChannelId(), param.getStream(), sendRtpItem.getCallId());
+ if (sendRtpItem.getPlayType().equals(InviteStreamType.BROADCAST)
+ || sendRtpItem.getPlayType().equals(InviteStreamType.TALK)) {
+ AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId());
+ if (audioBroadcastCatch != null) {
+ // 鏉ヨ嚜涓婄骇骞冲彴鐨勫仠姝㈠璁�
+ logger.info("[鍋滄瀵硅] 鏉ヨ嚜涓婄骇锛屽钩鍙帮細{}, 閫氶亾锛歿}", sendRtpItem.getDeviceId(), sendRtpItem.getChannelId());
+ audioBroadcastManager.del(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId());
+ }
+ }
+ }
+ } catch (SipException | InvalidArgumentException | ParseException |
+ SsrcTransactionNotFoundException e) {
+ logger.error("[鍛戒护鍙戦�佸け璐 鍙戦�丅YE: {}", e.getMessage());
+ }
+ }
+ }
+ }
+ }
+ }
+ });
+ return HookResult.SUCCESS();
+ }
+
+ /**
+ * 娴佹棤浜鸿鐪嬫椂浜嬩欢锛岀敤鎴峰彲浠ラ�氳繃姝や簨浠堕�夋嫨鏄惁鍏抽棴鏃犱汉鐪嬬殑娴併��
+ */
+ @ResponseBody
+ @PostMapping(value = "/on_stream_none_reader", produces = "application/json;charset=UTF-8")
+ public JSONObject onStreamNoneReader(@RequestBody OnStreamNoneReaderHookParam param) {
+
+ logger.info("[ABL HOOK]娴佹棤浜鸿鐪嬶細{}->{}->{}/{}", param.getMediaServerId(), param.getSchema(),
+ param.getApp(), param.getStream());
+ JSONObject ret = new JSONObject();
+ ret.put("code", 0);
+ // 鍥芥爣绫诲瀷鐨勬祦
+ if ("rtp".equals(param.getApp())) {
+ ret.put("close", userSetting.getStreamOnDemand());
+ // 鍥芥爣娴侊紝 鐐规挱/褰曞儚鍥炴斁/褰曞儚涓嬭浇
+ InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, param.getStream());
+ // 鐐规挱
+ if (inviteInfo != null) {
+ // 褰曞儚涓嬭浇
+ if (inviteInfo.getType() == InviteSessionType.DOWNLOAD) {
+ ret.put("close", false);
+ return ret;
+ }
+ // 鏀跺埌鏃犱汉瑙傜湅璇存槑娴佷篃娌℃湁鍦ㄥ線涓婄骇鎺ㄩ��
+ 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 {
+ commanderFroPlatform.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()) {
+ MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0,
+ sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getChannelId(),
+ sendRtpItem.getPlatformId(), parentPlatform.getName(), userSetting.getServerId(), sendRtpItem.getMediaServerId());
+ messageForPushChannel.setPlatFormIndex(parentPlatform.getId());
+ redisCatchStorage.sendPlatformStopPlayMsg(messageForPushChannel);
+ }
+ }
+ }
+ }
+ 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) {
+ cmder.streamByeCmd(device, inviteInfo.getChannelId(),
+ inviteInfo.getStream(), null);
+ } else {
+ logger.info("[鏃犱汉瑙傜湅] 鏈壘鍒拌澶囩殑鐐规挱淇℃伅锛� {}锛� 娴侊細{}", inviteInfo.getDeviceId(), param.getStream());
+ }
+ } catch (InvalidArgumentException | ParseException | SipException |
+ SsrcTransactionNotFoundException e) {
+ logger.error("[鏃犱汉瑙傜湅]鐐规挱锛� 鍙戦�丅YE澶辫触 {}", e.getMessage());
+ }
+ } else {
+ logger.info("[鏃犱汉瑙傜湅] 鏈壘鍒拌澶囷細 {}锛屾祦锛歿}", inviteInfo.getDeviceId(), param.getStream());
+ }
+
+ inviteStreamService.removeInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId(),
+ inviteInfo.getChannelId(), inviteInfo.getStream());
+ storager.stopPlay(inviteInfo.getDeviceId(), inviteInfo.getChannelId());
+ return ret;
+ }
+ SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, param.getStream(), null);
+ if (sendRtpItem != null && "talk".equals(sendRtpItem.getApp())) {
+ ret.put("close", false);
+ return ret;
+ }
+ } else if ("talk".equals(param.getApp()) || "broadcast".equals(param.getApp())) {
+ ret.put("close", false);
+ } else {
+ // 闈炲浗鏍囨祦 鎺ㄦ祦/鎷夋祦浠g悊
+ // 鎷夋祦浠g悊
+ StreamProxyItem streamProxyItem = streamProxyService.getStreamProxyByAppAndStream(param.getApp(), param.getStream());
+ if (streamProxyItem != null) {
+ if (streamProxyItem.isEnableRemoveNoneReader()) {
+ // 鏃犱汉瑙傜湅鑷姩绉婚櫎
+ ret.put("close", true);
+ streamProxyService.del(param.getApp(), param.getStream());
+ String url = streamProxyItem.getUrl() != null ? streamProxyItem.getUrl() : streamProxyItem.getSrcUrl();
+ logger.info("[{}/{}]<-[{}] 鎷夋祦浠g悊鏃犱汉瑙傜湅宸茬粡绉婚櫎", param.getApp(), param.getStream(), url);
+ } else if (streamProxyItem.isEnableDisableNoneReader()) {
+ // 鏃犱汉瑙傜湅鍋滅敤
+ ret.put("close", true);
+ // 淇敼鏁版嵁
+ streamProxyService.stop(param.getApp(), param.getStream());
+ } else {
+ // 鏃犱汉瑙傜湅涓嶅仛澶勭悊
+ ret.put("close", false);
+ }
+ return ret;
+ }
+ // TODO 鎺ㄦ祦鍏锋湁涓诲姩鎬э紝鏆傛椂涓嶅仛澶勭悊
+// StreamPushItem streamPushItem = streamPushService.getPush(app, streamId);
+// if (streamPushItem != null) {
+// // TODO 鍙戦�佸仠姝�
+//
+// }
+ }
+ return ret;
+ }
+
+ /**
+ * 娴佹湭鎵惧埌浜嬩欢锛岀敤鎴峰彲浠ュ湪姝や簨浠惰Е鍙戞椂锛岀珛鍗冲幓鎷夋祦锛岃繖鏍峰彲浠ュ疄鐜版寜闇�鎷夋祦锛涙浜嬩欢瀵瑰洖澶嶄笉鏁忔劅銆�
+ */
+ @ResponseBody
+ @PostMapping(value = "/on_stream_not_found", produces = "application/json;charset=UTF-8")
+ public DeferredResult<HookResult> onStreamNotFound(@RequestBody OnStreamNotFoundHookParam param) {
+ logger.info("[ABL HOOK] 娴佹湭鎵惧埌锛歿}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream());
+
+ DeferredResult<HookResult> defaultResult = new DeferredResult<>();
+
+ MediaServer mediaInfo = mediaServerService.getOne(param.getMediaServerId());
+ if (!userSetting.isAutoApplyPlay() || mediaInfo == null) {
+ defaultResult.setResult(new HookResult(ErrorCode.ERROR404.getCode(), ErrorCode.ERROR404.getMsg()));
+ return defaultResult;
+ }
+
+ if ("rtp".equals(param.getApp())) {
+ String[] s = param.getStream().split("_");
+ if ((s.length != 2 && s.length != 4)) {
+ defaultResult.setResult(HookResult.SUCCESS());
+ return defaultResult;
+ }
+ String deviceId = s[0];
+ String channelId = s[1];
+ Device device = redisCatchStorage.getDevice(deviceId);
+ if (device == null || !device.isOnLine()) {
+ defaultResult.setResult(new HookResult(ErrorCode.ERROR404.getCode(), ErrorCode.ERROR404.getMsg()));
+ return defaultResult;
+ }
+ DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId);
+ if (deviceChannel == null) {
+ defaultResult.setResult(new HookResult(ErrorCode.ERROR404.getCode(), ErrorCode.ERROR404.getMsg()));
+ return defaultResult;
+ }
+ if (s.length == 2) {
+ logger.info("[ABL HOOK] 棰勮娴佹湭鎵惧埌, 鍙戣捣鑷姩鐐规挱锛歿}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream());
+
+ RequestMessage msg = new RequestMessage();
+ String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId;
+ boolean exist = resultHolder.exist(key, null);
+ msg.setKey(key);
+ String uuid = UUID.randomUUID().toString();
+ msg.setId(uuid);
+ DeferredResult<HookResult> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue());
+
+ result.onTimeout(() -> {
+ logger.info("[ABL HOOK] 棰勮娴佽嚜鍔ㄧ偣鎾�, 绛夊緟瓒呮椂");
+ msg.setData(new HookResult(ErrorCode.ERROR100.getCode(), "鐐规挱瓒呮椂"));
+ resultHolder.invokeAllResult(msg);
+ inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId);
+ storager.stopPlay(deviceId, channelId);
+ });
+
+ resultHolder.put(key, uuid, result);
+
+ if (!exist) {
+ playService.play(mediaInfo, deviceId, channelId, null, (code, message, data) -> {
+ msg.setData(new HookResult(code, message));
+ resultHolder.invokeResult(msg);
+ });
+ }
+ return result;
+ } else if (s.length == 4) {
+ // 姝ゆ椂涓哄綍鍍忓洖鏀撅紝 褰曞儚鍥炴斁鏍煎紡涓�> 璁惧ID_閫氶亾ID_寮�濮嬫椂闂確缁撴潫鏃堕棿
+ String startTimeStr = s[2];
+ String endTimeStr = s[3];
+ if (startTimeStr == null || endTimeStr == null || startTimeStr.length() != 14 || endTimeStr.length() != 14) {
+ defaultResult.setResult(HookResult.SUCCESS());
+ return defaultResult;
+ }
+ String startTime = DateUtil.urlToyyyy_MM_dd_HH_mm_ss(startTimeStr);
+ String endTime = DateUtil.urlToyyyy_MM_dd_HH_mm_ss(endTimeStr);
+ logger.info("[ABL HOOK] 鍥炴斁娴佹湭鎵惧埌, 鍙戣捣鑷姩鐐规挱锛歿}->{}->{}/{}-{}-{}",
+ param.getMediaServerId(), param.getSchema(),
+ param.getApp(), param.getStream(),
+ startTime, endTime
+ );
+ RequestMessage msg = new RequestMessage();
+ String key = DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId;
+ boolean exist = resultHolder.exist(key, null);
+ msg.setKey(key);
+ String uuid = UUID.randomUUID().toString();
+ msg.setId(uuid);
+ DeferredResult<HookResult> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue());
+
+ result.onTimeout(() -> {
+ logger.info("[ABL HOOK] 鍥炴斁娴佽嚜鍔ㄧ偣鎾�, 绛夊緟瓒呮椂");
+ // 閲婃斁rtpserver
+ msg.setData(new HookResult(ErrorCode.ERROR100.getCode(), "鐐规挱瓒呮椂"));
+ resultHolder.invokeResult(msg);
+ });
+
+ resultHolder.put(key, uuid, result);
+
+ if (!exist) {
+ SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaInfo, param.getStream(), null,
+ device.isSsrcCheck(), true, 0, false, false, device.getStreamModeForParam());
+ playService.playBack(mediaInfo, ssrcInfo, deviceId, channelId, startTime, endTime, (code, message, data) -> {
+ msg.setData(new HookResult(code, message));
+ resultHolder.invokeResult(msg);
+ });
+ }
+ return result;
+ } else {
+ defaultResult.setResult(HookResult.SUCCESS());
+ return defaultResult;
+ }
+
+ } else {
+ // 鎷夋祦浠g悊
+ StreamProxyItem streamProxyByAppAndStream = streamProxyService.getStreamProxyByAppAndStream(param.getApp(), param.getStream());
+ if (streamProxyByAppAndStream != null && streamProxyByAppAndStream.isEnableDisableNoneReader()) {
+ streamProxyService.start(param.getApp(), param.getStream());
+ }
+ DeferredResult<HookResult> result = new DeferredResult<>();
+ result.setResult(HookResult.SUCCESS());
+ return result;
+ }
+ }
+
+ /**
+ * 鏈嶅姟鍣ㄥ惎鍔ㄤ簨浠讹紝鍙互鐢ㄤ簬鐩戝惉鏈嶅姟鍣ㄥ穿婧冮噸鍚紱姝や簨浠跺鍥炲涓嶆晱鎰熴��
+ */
+ @ResponseBody
+ @PostMapping(value = "/on_server_started", produces = "application/json;charset=UTF-8")
+ public HookResult onServerStarted(HttpServletRequest request, @RequestBody JSONObject jsonObject) {
+
+ jsonObject.put("ip", request.getRemoteAddr());
+ ZLMServerConfig zlmServerConfig = JSON.to(ZLMServerConfig.class, jsonObject);
+ zlmServerConfig.setIp(request.getRemoteAddr());
+ logger.info("[ABL HOOK] ABL 鍚姩 " + zlmServerConfig.getGeneralMediaServerId());
+ taskExecutor.execute(() -> {
+ List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_started);
+ if (subscribes != null && !subscribes.isEmpty()) {
+ for (ZlmHttpHookSubscribe.Event subscribe : subscribes) {
+ subscribe.response(null, zlmServerConfig);
+ }
+ }
+ });
+ try {
+ HookZlmServerStartEvent event = new HookZlmServerStartEvent(this);
+ MediaServer mediaServerItem = mediaServerService.getOne(zlmServerConfig.getMediaServerId());
+ if (mediaServerItem != null) {
+ event.setMediaServerItem(mediaServerItem);
+ applicationEventPublisher.publishEvent(event);
+ }
+ }catch (Exception e) {
+ logger.info("[ABL-HOOK-ABL鍚姩] 鍙戦�侀�氱煡澶辫触 ", e);
+ }
+
+ return HookResult.SUCCESS();
+ }
+
+ /**
+ * 鍙戦�乺tp(startSendRtp)琚姩鍏抽棴鏃跺洖璋�
+ */
+ @ResponseBody
+ @PostMapping(value = "/on_send_rtp_stopped", produces = "application/json;charset=UTF-8")
+ public HookResult onSendRtpStopped(HttpServletRequest request, @RequestBody OnSendRtpStoppedHookParam param) {
+
+ logger.info("[ABL HOOK] rtp鍙戦�佸叧闂細{}->{}/{}", param.getMediaServerId(), param.getApp(), param.getStream());
+
+ // 鏌ユ壘瀵瑰簲鐨勪笂绾ф帹娴侊紝鍙戦�佸仠姝�
+ if (!"rtp".equals(param.getApp())) {
+ return HookResult.SUCCESS();
+ }
+ taskExecutor.execute(() -> {
+ List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByStream(param.getStream());
+ if (sendRtpItems.size() > 0) {
+ for (SendRtpItem sendRtpItem : sendRtpItems) {
+ ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId());
+ ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrc());
+ try {
+ commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId());
+ } catch (SipException | InvalidArgumentException | ParseException e) {
+ logger.error("[鍛戒护鍙戦�佸け璐 鍥芥爣绾ц仈 鍙戦�丅YE: {}", e.getMessage());
+ }
+ redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(),
+ sendRtpItem.getCallId(), sendRtpItem.getStream());
+ }
+ }
+ });
+
+ return HookResult.SUCCESS();
+ }
+
+ /**
+ * rtpServer鏀舵祦瓒呮椂
+ */
+ @ResponseBody
+ @PostMapping(value = "/on_rtp_server_timeout", produces = "application/json;charset=UTF-8")
+ public HookResult onRtpServerTimeout(@RequestBody OnRtpServerTimeoutHookParam
+ param) {
+ logger.info("[ABL HOOK] rtpServer鏀舵祦瓒呮椂锛歿}->{}({})", param.getMediaServerId(), param.getStream_id(), param.getSsrc());
+
+ taskExecutor.execute(() -> {
+ List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_rtp_server_timeout);
+ if (subscribes != null && !subscribes.isEmpty()) {
+ for (ZlmHttpHookSubscribe.Event subscribe : subscribes) {
+ subscribe.response(null, param);
+ }
+ }
+ });
+
+ return HookResult.SUCCESS();
+ }
+
+ /**
+ * 褰曞儚瀹屾垚浜嬩欢
+ */
+ @ResponseBody
+ @PostMapping(value = "/on_record_mp4", produces = "application/json;charset=UTF-8")
+ public HookResult onRecordMp4(HttpServletRequest request, @RequestBody OnRecordMp4HookParam param) {
+ logger.info("[AB HOOK] 褰曞儚瀹屾垚浜嬩欢锛歿}->{}", param.getMediaServerId(), param.getFile_path());
+
+ taskExecutor.execute(() -> {
+ List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_record_mp4);
+ if (subscribes != null && !subscribes.isEmpty()) {
+ for (ZlmHttpHookSubscribe.Event subscribe : subscribes) {
+ subscribe.response(null, param);
+ }
+ }
+ cloudRecordService.addRecord(param);
+
+ });
+
+ return HookResult.SUCCESS();
+ }
+
+ private Map<String, String> urlParamToMap(String params) {
+ HashMap<String, String> map = new HashMap<>();
+ if (ObjectUtils.isEmpty(params)) {
+ return map;
+ }
+ String[] paramsArray = params.split("&");
+ if (paramsArray.length == 0) {
+ return map;
+ }
+ for (String param : paramsArray) {
+ String[] paramArray = param.split("=");
+ if (paramArray.length == 2) {
+ map.put(paramArray[0], paramArray[1]);
+ }
+ }
+ return map;
+ }
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/media/abl/ABLMediaServerStatusManger.java b/src/main/java/com/genersoft/iot/vmp/media/abl/ABLMediaServerStatusManger.java
new file mode 100644
index 0000000..28181e8
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/media/abl/ABLMediaServerStatusManger.java
@@ -0,0 +1,305 @@
+package com.genersoft.iot.vmp.media.abl;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
+import com.genersoft.iot.vmp.conf.DynamicTask;
+import com.genersoft.iot.vmp.conf.UserSetting;
+import com.genersoft.iot.vmp.media.abl.bean.AblServerConfig;
+import com.genersoft.iot.vmp.media.abl.event.HookAblServerKeepaliveEvent;
+import com.genersoft.iot.vmp.media.abl.event.HookAblServerStartEvent;
+import com.genersoft.iot.vmp.media.event.MediaServerChangeEvent;
+import com.genersoft.iot.vmp.media.event.MediaServerDeleteEvent;
+import com.genersoft.iot.vmp.media.service.IMediaServerService;
+import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
+import com.genersoft.iot.vmp.media.zlm.dto.ZLMServerConfig;
+import com.genersoft.iot.vmp.media.zlm.event.HookZlmServerKeepaliveEvent;
+import com.genersoft.iot.vmp.media.zlm.event.HookZlmServerStartEvent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.event.EventListener;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+import org.springframework.util.ObjectUtils;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * 绠$悊zlm娴佸獟浣撹妭鐐圭殑鐘舵��
+ */
+@Component
+public class ABLMediaServerStatusManger {
+
+ private final static Logger logger = LoggerFactory.getLogger(ABLMediaServerStatusManger.class);
+
+ private final Map<Object, MediaServer> offlineABLPrimaryMap = new ConcurrentHashMap<>();
+ private final Map<Object, MediaServer> offlineAblsecondaryMap = new ConcurrentHashMap<>();
+ private final Map<Object, Long> offlineAblTimeMap = new ConcurrentHashMap<>();
+
+ @Autowired
+ private ABLRESTfulUtils ablResTfulUtils;
+
+ @Autowired
+ private IMediaServerService mediaServerService;
+
+ @Autowired
+ private DynamicTask dynamicTask;
+
+ @Value("${server.ssl.enabled:false}")
+ private boolean sslEnabled;
+
+ @Value("${server.port}")
+ private Integer serverPort;
+
+ @Autowired
+ private UserSetting userSetting;
+
+ private final String type = "abl";
+
+ @Async("taskExecutor")
+ @EventListener
+ public void onApplicationEvent(MediaServerChangeEvent event) {
+ if (event.getMediaServerItemList() == null
+ || event.getMediaServerItemList().isEmpty()) {
+ return;
+ }
+ for (MediaServer mediaServerItem : event.getMediaServerItemList()) {
+ if (!type.equals(mediaServerItem.getType())) {
+ continue;
+ }
+ logger.info("[ABL-娣诲姞寰呬笂绾胯妭鐐筣 ID锛�" + mediaServerItem.getId());
+ offlineABLPrimaryMap.put(mediaServerItem.getId(), mediaServerItem);
+ offlineAblTimeMap.put(mediaServerItem.getId(), System.currentTimeMillis());
+ }
+ }
+
+ @Async("taskExecutor")
+ @EventListener
+ public void onApplicationEvent(HookAblServerStartEvent event) {
+ if (event.getMediaServerItem() == null
+ || !type.equals(event.getMediaServerItem().getType())
+ || event.getMediaServerItem().isStatus()) {
+ return;
+ }
+ MediaServer serverItem = mediaServerService.getOne(event.getMediaServerItem().getId());
+ if (serverItem == null) {
+ return;
+ }
+ logger.info("[ABL-HOOK浜嬩欢-鏈嶅姟鍚姩] ID锛�" + event.getMediaServerItem().getId());
+ online(serverItem, null);
+ }
+
+ @Async("taskExecutor")
+ @EventListener
+ public void onApplicationEvent(HookAblServerKeepaliveEvent event) {
+ if (event.getMediaServerItem() == null) {
+ return;
+ }
+ MediaServer serverItem = mediaServerService.getOne(event.getMediaServerItem().getId());
+ if (serverItem == null) {
+ return;
+ }
+ logger.info("[ABL-HOOK浜嬩欢-蹇冭烦] ID锛�" + event.getMediaServerItem().getId());
+ online(serverItem, null);
+ }
+
+ @Async("taskExecutor")
+ @EventListener
+ public void onApplicationEvent(MediaServerDeleteEvent event) {
+ if (event.getMediaServerId() == null) {
+ return;
+ }
+ logger.info("[ABL-鑺傜偣琚Щ闄 ID锛�" + event.getMediaServerId());
+ offlineABLPrimaryMap.remove(event.getMediaServerId());
+ offlineAblsecondaryMap.remove(event.getMediaServerId());
+ offlineAblTimeMap.remove(event.getMediaServerId());
+ }
+
+ @Scheduled(fixedDelay = 10*1000) //姣忛殧10绉掓鏌ヤ竴娆�
+ public void execute(){
+ // 鍒濇鍔犲叆鐨勭绾胯妭鐐逛細鍦�30鍒嗛挓鍐咃紝姣忛棿闅斿崄绉掑皾璇曚竴娆★紝30鍒嗛挓鍚庡鏋滀粛鐒舵病鏈変笂绾匡紝鍒欐瘡闅�30鍒嗛挓灏濊瘯涓�娆¤繛鎺�
+ if (offlineABLPrimaryMap.isEmpty() && offlineAblsecondaryMap.isEmpty()) {
+ return;
+ }
+ if (!offlineABLPrimaryMap.isEmpty()) {
+ for (MediaServer mediaServerItem : offlineABLPrimaryMap.values()) {
+ if (offlineAblTimeMap.get(mediaServerItem.getId()) < System.currentTimeMillis() - 30*60*1000) {
+ offlineAblsecondaryMap.put(mediaServerItem.getId(), mediaServerItem);
+ offlineABLPrimaryMap.remove(mediaServerItem.getId());
+ continue;
+ }
+ logger.info("[ABL-灏濊瘯杩炴帴] ID锛歿}, 鍦板潃锛� {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
+ JSONObject responseJson = ablResTfulUtils.getMediaServerConfig(mediaServerItem);
+ AblServerConfig ablServerConfig = null;
+ if (responseJson == null) {
+ logger.info("[ABL-灏濊瘯杩炴帴]澶辫触, ID锛歿}, 鍦板潃锛� {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
+ continue;
+ }
+ JSONArray data = responseJson.getJSONArray("data");
+ if (data == null || data.isEmpty()) {
+ logger.info("[ABL-灏濊瘯杩炴帴]澶辫触, ID锛歿}, 鍦板潃锛� {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
+ }else {
+ ablServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), AblServerConfig.class);
+ initPort(mediaServerItem, ablServerConfig);
+ online(mediaServerItem, ablServerConfig);
+ }
+ }
+ }
+ if (!offlineAblsecondaryMap.isEmpty()) {
+ for (MediaServer mediaServerItem : offlineAblsecondaryMap.values()) {
+ if (offlineAblTimeMap.get(mediaServerItem.getId()) < System.currentTimeMillis() - 30*60*1000) {
+ continue;
+ }
+ logger.info("[ABL-灏濊瘯杩炴帴] ID锛歿}, 鍦板潃锛� {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
+ JSONObject responseJson = ablResTfulUtils.getMediaServerConfig(mediaServerItem);
+ ZLMServerConfig zlmServerConfig = null;
+ if (responseJson == null) {
+ logger.info("[ABL-灏濊瘯杩炴帴]澶辫触, ID锛歿}, 鍦板潃锛� {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
+ offlineAblTimeMap.put(mediaServerItem.getId(), System.currentTimeMillis());
+ continue;
+ }
+ JSONArray data = responseJson.getJSONArray("data");
+ if (data == null || data.isEmpty()) {
+ logger.info("[ABL-灏濊瘯杩炴帴]澶辫触, ID锛歿}, 鍦板潃锛� {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
+ offlineAblTimeMap.put(mediaServerItem.getId(), System.currentTimeMillis());
+ }else {
+ zlmServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class);
+ initPort(mediaServerItem, zlmServerConfig);
+ online(mediaServerItem, zlmServerConfig);
+ }
+ }
+ }
+ }
+
+ private void online(MediaServer mediaServerItem, AblServerConfig config) {
+ offlineABLPrimaryMap.remove(mediaServerItem.getId());
+ offlineAblsecondaryMap.remove(mediaServerItem.getId());
+ offlineAblTimeMap.remove(mediaServerItem.getId());
+ if (!mediaServerItem.isStatus()) {
+ logger.info("[ABL-杩炴帴鎴愬姛] ID锛歿}, 鍦板潃锛� {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
+ mediaServerItem.setStatus(true);
+ mediaServerItem.setHookAliveInterval(10F);
+ mediaServerService.update(mediaServerItem);
+ if(mediaServerItem.isAutoConfig()) {
+ if (config == null) {
+ JSONObject responseJSON = ablResTfulUtils.getMediaServerConfig(mediaServerItem);
+ JSONArray data = responseJSON.getJSONArray("data");
+ if (data != null && !data.isEmpty()) {
+ config = JSON.parseObject(JSON.toJSONString(data.get(0)), AblServerConfig.class);
+ }
+ }
+ if (config != null) {
+ initPort(mediaServerItem, config);
+ setZLMConfig(mediaServerItem, "0".equals(config.getHookEnable())
+ || !Objects.equals(mediaServerItem.getHookAliveInterval(), config.getHookAliveInterval()));
+ }
+ }
+ mediaServerService.update(mediaServerItem);
+ }
+ // 璁剧疆涓ゆ蹇冭烦鏈敹鍒板垯璁や负zlm绂荤嚎
+ String key = "ABL-keepalive-" + mediaServerItem.getId();
+ dynamicTask.startDelay(key, ()->{
+ logger.warn("[ABL-蹇冭烦瓒呮椂] ID锛歿}", mediaServerItem.getId());
+ mediaServerItem.setStatus(false);
+ offlineABLPrimaryMap.put(mediaServerItem.getId(), mediaServerItem);
+ offlineAblTimeMap.put(mediaServerItem.getId(), System.currentTimeMillis());
+ // TODO 鍙戦�佺绾块�氱煡
+ mediaServerService.update(mediaServerItem);
+ }, (int)(mediaServerItem.getHookAliveInterval() * 2 * 1000));
+ }
+ private void initPort(MediaServer mediaServerItem, AblServerConfig ablServerConfig) {
+ // 绔彛鍙細浠庨厤缃腑璇诲彇涓�娆★紝涓�鏃﹁嚜宸遍厤缃垨鑰呰鍙栬繃浜嗗皢涓嶅湪閰嶇疆
+ if (mediaServerItem.getHttpSSlPort() == 0) {
+ mediaServerItem.setHttpSSlPort(ablServerConfig.getHttpSSLport());
+ }
+ if (mediaServerItem.getRtmpPort() == 0) {
+ mediaServerItem.setRtmpPort(ablServerConfig.getRtmpPort());
+ }
+ if (mediaServerItem.getRtmpSSlPort() == 0) {
+ mediaServerItem.setRtmpSSlPort(ablServerConfig.getRtmpSslPort());
+ }
+ if (mediaServerItem.getRtspPort() == 0) {
+ mediaServerItem.setRtspPort(ablServerConfig.getRtspPort());
+ }
+ if (mediaServerItem.getRtspSSLPort() == 0) {
+ mediaServerItem.setRtspSSLPort(ablServerConfig.getRtspSSlport());
+ }
+ if (mediaServerItem.getRtpProxyPort() == 0) {
+ mediaServerItem.setRtpProxyPort(ablServerConfig.getRtpProxyPort());
+ }
+ mediaServerItem.setHookAliveInterval(10F);
+ }
+
+ public void setZLMConfig(MediaServer mediaServerItem, boolean restart) {
+ logger.info("[濯掍綋鏈嶅姟鑺傜偣] 姝e湪璁剧疆 锛歿} -> {}:{}",
+ mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
+ String protocol = sslEnabled ? "https" : "http";
+ String hookPrefix = String.format("%s://%s:%s/index/hook", protocol, mediaServerItem.getHookIp(), serverPort);
+
+ Map<String, Object> param = new HashMap<>();
+ param.put("api.secret",mediaServerItem.getSecret()); // -profile:v Baseline
+ if (mediaServerItem.getRtspPort() != 0) {
+ param.put("ffmpeg.snap", "%s -rtsp_transport tcp -i %s -y -f mjpeg -frames:v 1 %s");
+ }
+ param.put("hook.enable","1");
+ param.put("hook.on_flow_report","");
+ param.put("hook.on_play",String.format("%s/on_play", hookPrefix));
+ param.put("hook.on_http_access","");
+ param.put("hook.on_publish", String.format("%s/on_publish", hookPrefix));
+ param.put("hook.on_record_ts","");
+ param.put("hook.on_rtsp_auth","");
+ param.put("hook.on_rtsp_realm","");
+ param.put("hook.on_server_started",String.format("%s/on_server_started", hookPrefix));
+ param.put("hook.on_shell_login","");
+ param.put("hook.on_stream_changed",String.format("%s/on_stream_changed", hookPrefix));
+ param.put("hook.on_stream_none_reader",String.format("%s/on_stream_none_reader", hookPrefix));
+ param.put("hook.on_stream_not_found",String.format("%s/on_stream_not_found", hookPrefix));
+ param.put("hook.on_server_keepalive",String.format("%s/on_server_keepalive", hookPrefix));
+ param.put("hook.on_send_rtp_stopped",String.format("%s/on_send_rtp_stopped", hookPrefix));
+ param.put("hook.on_rtp_server_timeout",String.format("%s/on_rtp_server_timeout", hookPrefix));
+ param.put("hook.on_record_mp4",String.format("%s/on_record_mp4", hookPrefix));
+ param.put("hook.timeoutSec","30");
+ param.put("hook.alive_interval", mediaServerItem.getHookAliveInterval());
+ // 鎺ㄦ祦鏂紑鍚庡彲浠ュ湪瓒呮椂鏃堕棿鍐呴噸鏂拌繛鎺ヤ笂缁х画鎺ㄦ祦锛岃繖鏍锋挱鏀惧櫒浼氭帴鐫�鎾斁銆�
+ // 缃�0鍏抽棴姝ょ壒鎬�(鎺ㄦ祦鏂紑浼氬鑷寸珛鍗虫柇寮�鎾斁鍣�)
+ // 姝ゅ弬鏁颁笉搴斿ぇ浜庢挱鏀惧櫒瓒呮椂鏃堕棿
+ // 浼樺寲姝ゆ秷鎭互鏇村揩鐨勬敹鍒版祦娉ㄩ攢浜嬩欢
+ param.put("protocol.continue_push_ms", "3000" );
+ // 鏈�澶氱瓑寰呮湭鍒濆鍖栫殑Track鏃堕棿锛屽崟浣嶆绉掞紝瓒呮椂涔嬪悗浼氬拷鐣ユ湭鍒濆鍖栫殑Track, 璁剧疆姝ら�夐」浼樺寲閭d簺闊抽閿欒鐨勪笉瑙勮寖娴侊紝
+ // 绛墇lm鏀寔缁欐瘡涓猺tpServer璁剧疆鍏抽棴闊抽鐨勬椂鍊欏彲浠ヤ笉璁剧疆姝ら�夐」
+ if (mediaServerItem.isRtpEnable() && !ObjectUtils.isEmpty(mediaServerItem.getRtpPortRange())) {
+ param.put("rtp_proxy.port_range", mediaServerItem.getRtpPortRange().replace(",", "-"));
+ }
+
+ if (!ObjectUtils.isEmpty(mediaServerItem.getRecordPath())) {
+ File recordPathFile = new File(mediaServerItem.getRecordPath());
+ param.put("protocol.mp4_save_path", recordPathFile.getParentFile().getPath());
+ param.put("protocol.downloadRoot", recordPathFile.getParentFile().getPath());
+ param.put("record.appName", recordPathFile.getName());
+ }
+
+ JSONObject responseJSON = ablResTfulUtils.setServerConfig(mediaServerItem, param);
+
+ if (responseJSON != null && responseJSON.getInteger("code") == 0) {
+ if (restart) {
+ logger.info("[濯掍綋鏈嶅姟鑺傜偣] 璁剧疆鎴愬姛,寮�濮嬮噸鍚互淇濊瘉閰嶇疆鐢熸晥 {} -> {}:{}",
+ mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
+ ablResTfulUtils.restartServer(mediaServerItem);
+ }else {
+ logger.info("[濯掍綋鏈嶅姟鑺傜偣] 璁剧疆鎴愬姛 {} -> {}:{}",
+ mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
+ }
+ }else {
+ logger.info("[濯掍綋鏈嶅姟鑺傜偣] 璁剧疆濯掍綋鏈嶅姟鑺傜偣澶辫触 {} -> {}:{}",
+ mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
+ }
+ }
+
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/media/abl/ABLRESTfulUtils.java b/src/main/java/com/genersoft/iot/vmp/media/abl/ABLRESTfulUtils.java
new file mode 100755
index 0000000..ce94324
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/media/abl/ABLRESTfulUtils.java
@@ -0,0 +1,403 @@
+package com.genersoft.iot.vmp.media.abl;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
+import okhttp3.*;
+import okhttp3.logging.HttpLoggingInterceptor;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.ConnectException;
+import java.net.SocketTimeoutException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class ABLRESTfulUtils {
+
+ private final static Logger logger = LoggerFactory.getLogger(ABLRESTfulUtils.class);
+
+ private OkHttpClient client;
+
+ public interface RequestCallback{
+ void run(JSONObject response);
+ }
+
+ private OkHttpClient getClient(){
+ return getClient(null);
+ }
+
+ private OkHttpClient getClient(Integer readTimeOut){
+ if (client == null) {
+ if (readTimeOut == null) {
+ readTimeOut = 10;
+ }
+ OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
+ //todo 鏆傛椂鍐欐瓒呮椂鏃堕棿 鍧囦负5s
+ // 璁剧疆杩炴帴瓒呮椂鏃堕棿
+ httpClientBuilder.connectTimeout(8,TimeUnit.SECONDS);
+ // 璁剧疆璇诲彇瓒呮椂鏃堕棿
+ httpClientBuilder.readTimeout(readTimeOut,TimeUnit.SECONDS);
+ // 璁剧疆杩炴帴姹�
+ httpClientBuilder.connectionPool(new ConnectionPool(16, 5, TimeUnit.MINUTES));
+ if (logger.isDebugEnabled()) {
+ HttpLoggingInterceptor logging = new HttpLoggingInterceptor(message -> {
+ logger.debug("http璇锋眰鍙傛暟锛�" + message);
+ });
+ logging.setLevel(HttpLoggingInterceptor.Level.BASIC);
+ // OkHttp閫茶娣诲姞鏀旀埅鍣╨oggingInterceptor
+ httpClientBuilder.addInterceptor(logging);
+ }
+ client = httpClientBuilder.build();
+ }
+ return client;
+
+ }
+
+ public JSONObject sendPost(MediaServer mediaServerItem, String api, Map<String, Object> param, RequestCallback callback) {
+ return sendPost(mediaServerItem, api, param, callback, null);
+ }
+
+
+ public JSONObject sendPost(MediaServer mediaServerItem, String api, Map<String, Object> param, RequestCallback callback, Integer readTimeOut) {
+ OkHttpClient client = getClient(readTimeOut);
+
+ if (mediaServerItem == null) {
+ return null;
+ }
+ String url = String.format("http://%s:%s/index/api/%s", mediaServerItem.getIp(), mediaServerItem.getHttpPort(), api);
+ JSONObject responseJSON = new JSONObject();
+ //-2鑷畾涔夋祦濯掍綋 璋冪敤閿欒鐮�
+ responseJSON.put("code",-2);
+ responseJSON.put("msg","娴佸獟浣撹皟鐢ㄥけ璐�");
+
+ FormBody.Builder builder = new FormBody.Builder();
+ builder.add("secret",mediaServerItem.getSecret());
+ if (param != null && param.keySet().size() > 0) {
+ for (String key : param.keySet()){
+ if (param.get(key) != null) {
+ builder.add(key, param.get(key).toString());
+ }
+ }
+ }
+
+ FormBody body = builder.build();
+
+ Request request = new Request.Builder()
+ .post(body)
+ .url(url)
+ .build();
+ if (callback == null) {
+ try {
+ Response response = client.newCall(request).execute();
+
+ if (response.isSuccessful()) {
+ ResponseBody responseBody = response.body();
+ if (responseBody != null) {
+ String responseStr = responseBody.string();
+ responseJSON = JSON.parseObject(responseStr);
+ }
+ }else {
+ System.out.println( 2222);
+ System.out.println( response.code());
+ response.close();
+ Objects.requireNonNull(response.body()).close();
+ }
+ }catch (IOException e) {
+ logger.error(String.format("[ %s ]璇锋眰澶辫触: %s", url, e.getMessage()));
+
+ if(e instanceof SocketTimeoutException){
+ //璇诲彇瓒呮椂瓒呮椂寮傚父
+ logger.error(String.format("璇诲彇ZLM鏁版嵁瓒呮椂澶辫触: %s, %s", url, e.getMessage()));
+ }
+ if(e instanceof ConnectException){
+ //鍒ゆ柇杩炴帴寮傚父锛屾垜杩欓噷鏄姤Failed to connect to 10.7.5.144
+ logger.error(String.format("杩炴帴ZLM杩炴帴澶辫触: %s, %s", url, e.getMessage()));
+ }
+
+ }catch (Exception e){
+ logger.error(String.format("璁块棶ZLM澶辫触: %s, %s", url, e.getMessage()));
+ }
+ }else {
+ client.newCall(request).enqueue(new Callback(){
+
+ @Override
+ public void onResponse(@NotNull Call call, @NotNull Response response){
+ if (response.isSuccessful()) {
+ try {
+ String responseStr = Objects.requireNonNull(response.body()).string();
+ callback.run(JSON.parseObject(responseStr));
+ } catch (IOException e) {
+ logger.error(String.format("[ %s ]璇锋眰澶辫触: %s", url, e.getMessage()));
+ }
+
+ }else {
+ response.close();
+ Objects.requireNonNull(response.body()).close();
+ }
+ }
+
+ @Override
+ public void onFailure(@NotNull Call call, @NotNull IOException e) {
+ logger.error(String.format("杩炴帴ZLM澶辫触: %s, %s", call.request().toString(), e.getMessage()));
+
+ if(e instanceof SocketTimeoutException){
+ //璇诲彇瓒呮椂瓒呮椂寮傚父
+ logger.error(String.format("璇诲彇ZLM鏁版嵁澶辫触: %s, %s", call.request().toString(), e.getMessage()));
+ }
+ if(e instanceof ConnectException){
+ //鍒ゆ柇杩炴帴寮傚父锛屾垜杩欓噷鏄姤Failed to connect to 10.7.5.144
+ logger.error(String.format("杩炴帴ZLM澶辫触: %s, %s", call.request().toString(), e.getMessage()));
+ }
+ }
+ });
+ }
+
+
+
+ return responseJSON;
+ }
+
+ public void sendGetForImg(MediaServer mediaServerItem, String api, Map<String, Object> params, String targetPath, String fileName) {
+ String url = String.format("http://%s:%s/index/api/%s", mediaServerItem.getIp(), mediaServerItem.getHttpPort(), api);
+ HttpUrl parseUrl = HttpUrl.parse(url);
+ if (parseUrl == null) {
+ return;
+ }
+ HttpUrl.Builder httpBuilder = parseUrl.newBuilder();
+
+ httpBuilder.addQueryParameter("secret", mediaServerItem.getSecret());
+ if (params != null) {
+ for (Map.Entry<String, Object> param : params.entrySet()) {
+ httpBuilder.addQueryParameter(param.getKey(), param.getValue().toString());
+ }
+ }
+
+ Request request = new Request.Builder()
+ .url(httpBuilder.build())
+ .build();
+ logger.info(request.toString());
+ try {
+ OkHttpClient client = getClient();
+ Response response = client.newCall(request).execute();
+ if (response.isSuccessful()) {
+ if (targetPath != null) {
+ File snapFolder = new File(targetPath);
+ if (!snapFolder.exists()) {
+ if (!snapFolder.mkdirs()) {
+ logger.warn("{}璺緞鍒涘缓澶辫触", snapFolder.getAbsolutePath());
+ }
+
+ }
+ File snapFile = new File(targetPath + File.separator + fileName);
+ FileOutputStream outStream = new FileOutputStream(snapFile);
+
+ outStream.write(Objects.requireNonNull(response.body()).bytes());
+ outStream.flush();
+ outStream.close();
+ } else {
+ logger.error(String.format("[ %s ]璇锋眰澶辫触: %s %s", url, response.code(), response.message()));
+ }
+ } else {
+ logger.error(String.format("[ %s ]璇锋眰澶辫触: %s %s", url, response.code(), response.message()));
+ }
+ Objects.requireNonNull(response.body()).close();
+ } catch (ConnectException e) {
+ logger.error(String.format("杩炴帴ZLM澶辫触: %s, %s", e.getCause().getMessage(), e.getMessage()));
+ logger.info("璇锋鏌edia閰嶇疆骞剁‘璁LM宸插惎鍔�...");
+ } catch (IOException e) {
+ logger.error(String.format("[ %s ]璇锋眰澶辫触: %s", url, e.getMessage()));
+ }
+ }
+
+ public JSONObject getMediaList(MediaServer mediaServerItem, String app, String stream, String schema, RequestCallback callback){
+ Map<String, Object> param = new HashMap<>();
+ if (app != null) {
+ param.put("app",app);
+ }
+ if (stream != null) {
+ param.put("stream",stream);
+ }
+ if (schema != null) {
+ param.put("schema",schema);
+ }
+ param.put("vhost","__defaultVhost__");
+ return sendPost(mediaServerItem, "getMediaList",param, callback);
+ }
+
+ public JSONObject getMediaList(MediaServer mediaServerItem, String app, String stream){
+ return getMediaList(mediaServerItem, app, stream,null, null);
+ }
+
+ public JSONObject getMediaList(MediaServer mediaServerItem, RequestCallback callback){
+ return sendPost(mediaServerItem, "getMediaList",null, callback);
+ }
+
+ public JSONObject getMediaInfo(MediaServer mediaServerItem, String app, String schema, String stream){
+ Map<String, Object> param = new HashMap<>();
+ param.put("app",app);
+ param.put("schema",schema);
+ param.put("stream",stream);
+ param.put("vhost","__defaultVhost__");
+ return sendPost(mediaServerItem, "getMediaInfo",param, null);
+ }
+
+ public JSONObject getRtpInfo(MediaServer mediaServerItem, String stream_id){
+ Map<String, Object> param = new HashMap<>();
+ param.put("stream_id",stream_id);
+ return sendPost(mediaServerItem, "getRtpInfo",param, null);
+ }
+
+ public JSONObject addFFmpegSource(MediaServer mediaServerItem, String src_url, String dst_url, Integer timeout_ms,
+ boolean enable_audio, boolean enable_mp4, String ffmpeg_cmd_key){
+ logger.info(src_url);
+ logger.info(dst_url);
+ Map<String, Object> param = new HashMap<>();
+ param.put("src_url", src_url);
+ param.put("dst_url", dst_url);
+ param.put("timeout_ms", timeout_ms);
+ param.put("enable_mp4", enable_mp4);
+ param.put("ffmpeg_cmd_key", ffmpeg_cmd_key);
+ return sendPost(mediaServerItem, "addFFmpegSource",param, null);
+ }
+
+ public JSONObject delFFmpegSource(MediaServer mediaServerItem, String key){
+ Map<String, Object> param = new HashMap<>();
+ param.put("key", key);
+ return sendPost(mediaServerItem, "delFFmpegSource",param, null);
+ }
+
+ public JSONObject delStreamProxy(MediaServer mediaServerItem, String key){
+ Map<String, Object> param = new HashMap<>();
+ param.put("key", key);
+ return sendPost(mediaServerItem, "delStreamProxy",param, null);
+ }
+
+ public JSONObject getMediaServerConfig(MediaServer mediaServerItem){
+ return sendPost(mediaServerItem, "getServerConfig",null, null);
+ }
+
+ public JSONObject setServerConfig(MediaServer mediaServerItem, Map<String, Object> param){
+ return sendPost(mediaServerItem,"setServerConfig",param, null);
+ }
+
+ public JSONObject openRtpServer(MediaServer mediaServerItem, Map<String, Object> param){
+ return sendPost(mediaServerItem, "openRtpServer",param, null);
+ }
+
+ public JSONObject closeRtpServer(MediaServer mediaServerItem, Map<String, Object> param) {
+ return sendPost(mediaServerItem, "closeRtpServer",param, null);
+ }
+
+ public void closeRtpServer(MediaServer mediaServerItem, Map<String, Object> param, RequestCallback callback) {
+ sendPost(mediaServerItem, "closeRtpServer",param, callback);
+ }
+
+ public JSONObject listRtpServer(MediaServer mediaServerItem) {
+ return sendPost(mediaServerItem, "listRtpServer",null, null);
+ }
+
+ public JSONObject startSendRtp(MediaServer mediaServerItem, Map<String, Object> param) {
+ return sendPost(mediaServerItem, "startSendRtp",param, null);
+ }
+
+ public JSONObject startSendRtpPassive(MediaServer mediaServerItem, Map<String, Object> param) {
+ return sendPost(mediaServerItem, "startSendRtpPassive",param, null);
+ }
+
+ public JSONObject startSendRtpPassive(MediaServer mediaServerItem, Map<String, Object> param, RequestCallback callback) {
+ return sendPost(mediaServerItem, "startSendRtpPassive",param, callback);
+ }
+
+ public JSONObject stopSendRtp(MediaServer mediaServerItem, Map<String, Object> param) {
+ return sendPost(mediaServerItem, "stopSendRtp",param, null);
+ }
+
+ public JSONObject restartServer(MediaServer mediaServerItem) {
+ return sendPost(mediaServerItem, "restartServer",null, null);
+ }
+
+ public JSONObject addStreamProxy(MediaServer mediaServerItem, String app, String stream, String url, boolean enable_audio, boolean enable_mp4, String rtp_type) {
+ Map<String, Object> param = new HashMap<>();
+ param.put("vhost", "__defaultVhost__");
+ param.put("app", app);
+ param.put("stream", stream);
+ param.put("url", url);
+ param.put("enable_mp4", enable_mp4?1:0);
+ param.put("enable_audio", enable_audio?1:0);
+ param.put("rtp_type", rtp_type);
+ return sendPost(mediaServerItem, "addStreamProxy",param, null, 20);
+ }
+
+ public JSONObject closeStreams(MediaServer mediaServerItem, String app, String stream) {
+ Map<String, Object> param = new HashMap<>();
+ param.put("vhost", "__defaultVhost__");
+ param.put("app", app);
+ param.put("stream", stream);
+ param.put("force", 1);
+ return sendPost(mediaServerItem, "close_streams",param, null);
+ }
+
+ public JSONObject getAllSession(MediaServer mediaServerItem) {
+ return sendPost(mediaServerItem, "getAllSession",null, null);
+ }
+
+ public void kickSessions(MediaServer mediaServerItem, String localPortSStr) {
+ Map<String, Object> param = new HashMap<>();
+ param.put("local_port", localPortSStr);
+ sendPost(mediaServerItem, "kick_sessions",param, null);
+ }
+
+ public void getSnap(MediaServer mediaServerItem, String streamUrl, int timeout_sec, int expire_sec, String targetPath, String fileName) {
+ Map<String, Object> param = new HashMap<>(3);
+ param.put("url", streamUrl);
+ param.put("timeout_sec", timeout_sec);
+ param.put("expire_sec", expire_sec);
+ sendGetForImg(mediaServerItem, "getSnap", param, targetPath, fileName);
+ }
+
+ public JSONObject pauseRtpCheck(MediaServer mediaServerItem, String streamId) {
+ Map<String, Object> param = new HashMap<>(1);
+ param.put("stream_id", streamId);
+ return sendPost(mediaServerItem, "pauseRtpCheck",param, null);
+ }
+
+ public JSONObject resumeRtpCheck(MediaServer mediaServerItem, String streamId) {
+ Map<String, Object> param = new HashMap<>(1);
+ param.put("stream_id", streamId);
+ return sendPost(mediaServerItem, "resumeRtpCheck",param, null);
+ }
+
+ public JSONObject connectRtpServer(MediaServer mediaServerItem, String dst_url, int dst_port, String stream_id) {
+ Map<String, Object> param = new HashMap<>(1);
+ param.put("dst_url", dst_url);
+ param.put("dst_port", dst_port);
+ param.put("stream_id", stream_id);
+ return sendPost(mediaServerItem, "connectRtpServer",param, null);
+ }
+
+ public JSONObject updateRtpServerSSRC(MediaServer mediaServerItem, String streamId, String ssrc) {
+ Map<String, Object> param = new HashMap<>(1);
+ param.put("ssrc", ssrc);
+ param.put("stream_id", streamId);
+ return sendPost(mediaServerItem, "updateRtpServerSSRC",param, null);
+ }
+
+ public JSONObject deleteRecordDirectory(MediaServer mediaServerItem, String app, String stream, String date, String fileName) {
+ Map<String, Object> param = new HashMap<>(1);
+ param.put("vhost", "__defaultVhost__");
+ param.put("app", app);
+ param.put("stream", stream);
+ param.put("period", date);
+ param.put("name", fileName);
+ return sendPost(mediaServerItem, "deleteRecordDirectory",param, null);
+ }
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/media/abl/bean/AblServerConfig.java b/src/main/java/com/genersoft/iot/vmp/media/abl/bean/AblServerConfig.java
new file mode 100644
index 0000000..4898326
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/media/abl/bean/AblServerConfig.java
@@ -0,0 +1,4 @@
+package com.genersoft.iot.vmp.media.abl.bean;
+
+public class AblServerConfig {
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/media/abl/event/HookAblServerKeepaliveEvent.java b/src/main/java/com/genersoft/iot/vmp/media/abl/event/HookAblServerKeepaliveEvent.java
new file mode 100644
index 0000000..bbedd6d
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/media/abl/event/HookAblServerKeepaliveEvent.java
@@ -0,0 +1,24 @@
+package com.genersoft.iot.vmp.media.abl.event;
+
+import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
+import org.springframework.context.ApplicationEvent;
+
+/**
+ * zlm 蹇冭烦浜嬩欢
+ */
+public class HookAblServerKeepaliveEvent extends ApplicationEvent {
+
+ public HookAblServerKeepaliveEvent(Object source) {
+ super(source);
+ }
+
+ private MediaServer mediaServerItem;
+
+ public MediaServer getMediaServerItem() {
+ return mediaServerItem;
+ }
+
+ public void setMediaServerItem(MediaServer mediaServerItem) {
+ this.mediaServerItem = mediaServerItem;
+ }
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/media/abl/event/HookAblServerStartEvent.java b/src/main/java/com/genersoft/iot/vmp/media/abl/event/HookAblServerStartEvent.java
new file mode 100644
index 0000000..4e1960e
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/media/abl/event/HookAblServerStartEvent.java
@@ -0,0 +1,24 @@
+package com.genersoft.iot.vmp.media.abl.event;
+
+import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
+import org.springframework.context.ApplicationEvent;
+
+/**
+ * zlm server_start浜嬩欢
+ */
+public class HookAblServerStartEvent extends ApplicationEvent {
+
+ public HookAblServerStartEvent(Object source) {
+ super(source);
+ }
+
+ private MediaServer mediaServerItem;
+
+ public MediaServer getMediaServerItem() {
+ return mediaServerItem;
+ }
+
+ public void setMediaServerItem(MediaServer mediaServerItem) {
+ this.mediaServerItem = mediaServerItem;
+ }
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
index 01fc635..a247a78 100755
--- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -142,14 +142,6 @@
@PostMapping(value = "/on_server_keepalive", produces = "application/json;charset=UTF-8")
public HookResult onServerKeepalive(@RequestBody OnServerKeepaliveHookParam param) {
- taskExecutor.execute(() -> {
- List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_keepalive);
- if (subscribes != null && !subscribes.isEmpty()) {
- for (ZlmHttpHookSubscribe.Event subscribe : subscribes) {
- subscribe.response(null, param);
- }
- }
- });
try {
HookZlmServerKeepaliveEvent event = new HookZlmServerKeepaliveEvent(this);
MediaServer mediaServerItem = mediaServerService.getOne(param.getMediaServerId());
@@ -184,6 +176,7 @@
}
}
});
+ // TODO 姝ゅ閫昏緫閫傚悎杩佺Щ鍒癕ediaService涓�
if (!"rtp".equals(param.getApp())) {
Map<String, String> paramMap = urlParamToMap(param.getParams());
StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream());
@@ -208,8 +201,8 @@
// TODO 鍔犲揩澶勭悊閫熷害
String mediaServerId = json.getString("mediaServerId");
- MediaServer mediaInfo = mediaServerService.getOne(mediaServerId);
- if (mediaInfo == null) {
+ MediaServer mediaServer = mediaServerService.getOne(mediaServerId);
+ if (mediaServer == null) {
return new HookResultForOnPublish(200, "success");
}
// 鎺ㄦ祦閴存潈鐨勫鐞�
@@ -257,7 +250,7 @@
taskExecutor.execute(() -> {
ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_publish, json);
if (subscribe != null) {
- subscribe.response(mediaInfo, param);
+ subscribe.response(mediaServer, param);
}
});
@@ -273,7 +266,7 @@
InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, param.getStream());
// 鍗曠鍙fā寮忎笅淇敼娴� ID
- if (!mediaInfo.isRtpEnable() && inviteInfo == null) {
+ if (!mediaServer.isRtpEnable() && inviteInfo == null) {
String ssrc = String.format("%010d", Long.parseLong(param.getStream(), 16));
inviteInfo = inviteStreamService.getInviteInfoBySSRC(ssrc);
if (inviteInfo != null) {
--
Gitblit v1.8.0