hook优化
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
package com.genersoft.iot.vmp.media;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.MediaConfig;
|
||||
import com.genersoft.iot.vmp.media.event.MediaServerChangeEvent;
|
||||
import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerChangeEvent;
|
||||
import com.genersoft.iot.vmp.media.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@@ -8,8 +8,8 @@ import com.genersoft.iot.vmp.media.abl.bean.AblServerConfig;
|
||||
import com.genersoft.iot.vmp.media.abl.bean.ConfigKeyId;
|
||||
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.event.mediaServer.MediaServerChangeEvent;
|
||||
import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerDeleteEvent;
|
||||
import com.genersoft.iot.vmp.media.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
|
||||
import org.slf4j.Logger;
|
||||
@@ -20,11 +20,8 @@ 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.lang.reflect.Field;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.media.bean;
|
||||
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
@@ -12,6 +13,15 @@ import java.util.List;
|
||||
*/
|
||||
@Schema(description = "视频信息")
|
||||
public class MediaInfo {
|
||||
@Schema(description = "应用名")
|
||||
private String app;
|
||||
@Schema(description = "流ID")
|
||||
private String stream;
|
||||
@Schema(description = "流媒体节点")
|
||||
private MediaServer mediaServer;
|
||||
@Schema(description = "协议")
|
||||
private String schema;
|
||||
|
||||
@Schema(description = "观看人数")
|
||||
private Integer readerCount;
|
||||
@Schema(description = "视频编码类型")
|
||||
@@ -37,8 +47,15 @@ public class MediaInfo {
|
||||
@Schema(description = "数据产生速度,单位byte/s")
|
||||
private Long bytesSpeed;
|
||||
|
||||
public static MediaInfo getInstance(JSONObject jsonObject) {
|
||||
public static MediaInfo getInstance(JSONObject jsonObject, MediaServer mediaServer) {
|
||||
MediaInfo mediaInfo = new MediaInfo();
|
||||
mediaInfo.setMediaServer(mediaServer);
|
||||
String app = jsonObject.getString("app");
|
||||
mediaInfo.setApp(app);
|
||||
String stream = jsonObject.getString("stream");
|
||||
mediaInfo.setStream(stream);
|
||||
String schema = jsonObject.getString("schema");
|
||||
mediaInfo.setSchema(schema);
|
||||
Integer totalReaderCount = jsonObject.getInteger("totalReaderCount");
|
||||
Boolean online = jsonObject.getBoolean("online");
|
||||
Integer originType = jsonObject.getInteger("originType");
|
||||
@@ -110,9 +127,13 @@ public class MediaInfo {
|
||||
return mediaInfo;
|
||||
}
|
||||
|
||||
public static MediaInfo getInstance(OnStreamChangedHookParam param) {
|
||||
public static MediaInfo getInstance(OnStreamChangedHookParam param, MediaServer mediaServer) {
|
||||
List<OnStreamChangedHookParam.MediaTrack> tracks = param.getTracks();
|
||||
MediaInfo mediaInfo = new MediaInfo();
|
||||
mediaInfo.setApp(param.getApp());
|
||||
mediaInfo.setStream(param.getStream());
|
||||
mediaInfo.setSchema(param.getSchema());
|
||||
mediaInfo.setMediaServer(mediaServer);
|
||||
mediaInfo.setReaderCount(param.getTotalReaderCount());
|
||||
mediaInfo.setOnline(param.isRegist());
|
||||
mediaInfo.setOriginType(param.getOriginType());
|
||||
@@ -247,4 +268,36 @@ public class MediaInfo {
|
||||
public void setBytesSpeed(Long bytesSpeed) {
|
||||
this.bytesSpeed = bytesSpeed;
|
||||
}
|
||||
|
||||
public String getApp() {
|
||||
return app;
|
||||
}
|
||||
|
||||
public void setApp(String app) {
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
public String getStream() {
|
||||
return stream;
|
||||
}
|
||||
|
||||
public void setStream(String stream) {
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
public MediaServer getMediaServer() {
|
||||
return mediaServer;
|
||||
}
|
||||
|
||||
public void setMediaServer(MediaServer mediaServer) {
|
||||
this.mediaServer = mediaServer;
|
||||
}
|
||||
|
||||
public String getSchema() {
|
||||
return schema;
|
||||
}
|
||||
|
||||
public void setSchema(String schema) {
|
||||
this.schema = schema;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.genersoft.iot.vmp.media.bean;
|
||||
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam;
|
||||
|
||||
public class RecordInfo {
|
||||
private String fileName;
|
||||
private String filePath;
|
||||
private long fileSize;
|
||||
private String folder;
|
||||
private String url;
|
||||
private long startTime;
|
||||
private double timeLen;
|
||||
|
||||
public static RecordInfo getInstance(OnRecordMp4HookParam hookParam) {
|
||||
RecordInfo recordInfo = new RecordInfo();
|
||||
recordInfo.setFileName(hookParam.getFile_name());
|
||||
recordInfo.setUrl(hookParam.getUrl());
|
||||
recordInfo.setFolder(hookParam.getFolder());
|
||||
recordInfo.setFilePath(hookParam.getFile_path());
|
||||
recordInfo.setFileSize(hookParam.getFile_size());
|
||||
recordInfo.setStartTime(hookParam.getStart_time());
|
||||
recordInfo.setTimeLen(hookParam.getTime_len());
|
||||
return recordInfo;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public void setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public String getFilePath() {
|
||||
return filePath;
|
||||
}
|
||||
|
||||
public void setFilePath(String filePath) {
|
||||
this.filePath = filePath;
|
||||
}
|
||||
|
||||
public long getFileSize() {
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
public void setFileSize(long fileSize) {
|
||||
this.fileSize = fileSize;
|
||||
}
|
||||
|
||||
public String getFolder() {
|
||||
return folder;
|
||||
}
|
||||
|
||||
public void setFolder(String folder) {
|
||||
this.folder = folder;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public long getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public void setStartTime(long startTime) {
|
||||
this.startTime = startTime;
|
||||
}
|
||||
|
||||
public double getTimeLen() {
|
||||
return timeLen;
|
||||
}
|
||||
|
||||
public void setTimeLen(double timeLen) {
|
||||
this.timeLen = timeLen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RecordInfo{" +
|
||||
"文件名称='" + fileName + '\'' +
|
||||
", 文件路径='" + filePath + '\'' +
|
||||
", 文件大小=" + fileSize +
|
||||
", 开始时间=" + startTime +
|
||||
", 时长=" + timeLen +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
package com.genersoft.iot.vmp.media.event;
|
||||
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamNotFoundHookParam;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
/**
|
||||
* 流未找到
|
||||
*/
|
||||
public class MediaNotFoundEvent extends ApplicationEvent {
|
||||
public MediaNotFoundEvent(Object source) {
|
||||
super(source);
|
||||
}
|
||||
|
||||
private String app;
|
||||
|
||||
private String stream;
|
||||
|
||||
private MediaServer mediaServer;
|
||||
|
||||
private String schema;
|
||||
|
||||
public static MediaNotFoundEvent getInstance(Object source, OnStreamNotFoundHookParam hookParam, MediaServer mediaServer){
|
||||
MediaNotFoundEvent mediaDepartureEven = new MediaNotFoundEvent(source);
|
||||
mediaDepartureEven.setApp(hookParam.getApp());
|
||||
mediaDepartureEven.setStream(hookParam.getStream());
|
||||
mediaDepartureEven.setSchema(hookParam.getSchema());
|
||||
mediaDepartureEven.setMediaServer(mediaServer);
|
||||
return mediaDepartureEven;
|
||||
}
|
||||
|
||||
public String getApp() {
|
||||
return app;
|
||||
}
|
||||
|
||||
public void setApp(String app) {
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
public String getStream() {
|
||||
return stream;
|
||||
}
|
||||
|
||||
public void setStream(String stream) {
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
public MediaServer getMediaServer() {
|
||||
return mediaServer;
|
||||
}
|
||||
|
||||
public void setMediaServer(MediaServer mediaServer) {
|
||||
this.mediaServer = mediaServer;
|
||||
}
|
||||
|
||||
public String getSchema() {
|
||||
return schema;
|
||||
}
|
||||
|
||||
public void setSchema(String schema) {
|
||||
this.schema = schema;
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
package com.genersoft.iot.vmp.media.event;
|
||||
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamNotFoundHookParam;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
/**
|
||||
* rtp 服务收流超时通知
|
||||
*/
|
||||
public class MediaRtpServerTimeoutEvent extends ApplicationEvent {
|
||||
public MediaRtpServerTimeoutEvent(Object source) {
|
||||
super(source);
|
||||
}
|
||||
|
||||
private String app;
|
||||
|
||||
private String stream;
|
||||
|
||||
private MediaServer mediaServer;
|
||||
|
||||
public static MediaRtpServerTimeoutEvent getInstance(Object source, OnStreamNotFoundHookParam hookParam, MediaServer mediaServer){
|
||||
MediaRtpServerTimeoutEvent mediaDepartureEven = new MediaRtpServerTimeoutEvent(source);
|
||||
mediaDepartureEven.setApp(hookParam.getApp());
|
||||
mediaDepartureEven.setStream(hookParam.getStream());
|
||||
mediaDepartureEven.setMediaServer(mediaServer);
|
||||
return mediaDepartureEven;
|
||||
}
|
||||
|
||||
public String getApp() {
|
||||
return app;
|
||||
}
|
||||
|
||||
public void setApp(String app) {
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
public String getStream() {
|
||||
return stream;
|
||||
}
|
||||
|
||||
public void setStream(String stream) {
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
public MediaServer getMediaServer() {
|
||||
return mediaServer;
|
||||
}
|
||||
|
||||
public void setMediaServer(MediaServer mediaServer) {
|
||||
this.mediaServer = mediaServer;
|
||||
}
|
||||
}
|
||||
86
src/main/java/com/genersoft/iot/vmp/media/event/hook/Hook.java
Executable file
86
src/main/java/com/genersoft/iot/vmp/media/event/hook/Hook.java
Executable file
@@ -0,0 +1,86 @@
|
||||
package com.genersoft.iot.vmp.media.event.hook;
|
||||
|
||||
/**
|
||||
* zlm hook事件的参数
|
||||
* @author lin
|
||||
*/
|
||||
public class Hook {
|
||||
|
||||
private HookType hookType;
|
||||
|
||||
private String app;
|
||||
|
||||
private String stream;
|
||||
|
||||
private String mediaServerId;
|
||||
|
||||
private Long createTime;
|
||||
|
||||
public static Hook getInstance(HookType hookType, String app, String stream, String mediaServerId) {
|
||||
Hook hookSubscribe = new Hook();
|
||||
hookSubscribe.setApp(app);
|
||||
hookSubscribe.setStream(stream);
|
||||
hookSubscribe.setHookType(hookType);
|
||||
hookSubscribe.setMediaServerId(mediaServerId);
|
||||
hookSubscribe.setCreateTime(System.currentTimeMillis());
|
||||
return hookSubscribe;
|
||||
}
|
||||
|
||||
public HookType getHookType() {
|
||||
return hookType;
|
||||
}
|
||||
|
||||
public void setHookType(HookType hookType) {
|
||||
this.hookType = hookType;
|
||||
}
|
||||
|
||||
public String getApp() {
|
||||
return app;
|
||||
}
|
||||
|
||||
public void setApp(String app) {
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
public String getStream() {
|
||||
return stream;
|
||||
}
|
||||
|
||||
public void setStream(String stream) {
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
public Long getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(Long createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
|
||||
public String getMediaServerId() {
|
||||
return mediaServerId;
|
||||
}
|
||||
|
||||
public void setMediaServerId(String mediaServerId) {
|
||||
this.mediaServerId = mediaServerId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof Hook) {
|
||||
Hook param = (Hook) obj;
|
||||
return param.getHookType().equals(this.hookType)
|
||||
&& param.getApp().equals(this.app)
|
||||
&& param.getStream().equals(this.stream)
|
||||
&& param.getMediaServerId().equals(this.mediaServerId);
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getHookType() + this.getApp() + this.getStream() + this.getMediaServerId();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package com.genersoft.iot.vmp.media.event.hook;
|
||||
|
||||
import com.genersoft.iot.vmp.media.bean.MediaInfo;
|
||||
import com.genersoft.iot.vmp.media.bean.RecordInfo;
|
||||
import com.genersoft.iot.vmp.media.event.media.MediaArrivalEvent;
|
||||
import com.genersoft.iot.vmp.media.event.media.MediaEvent;
|
||||
import com.genersoft.iot.vmp.media.event.media.MediaPublishEvent;
|
||||
import com.genersoft.iot.vmp.media.event.media.MediaRecordMp4Event;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
/**
|
||||
* Hook返回的内容
|
||||
*/
|
||||
public class HookData {
|
||||
/**
|
||||
* 应用名
|
||||
*/
|
||||
private String app;
|
||||
/**
|
||||
* 流ID
|
||||
*/
|
||||
private String stream;
|
||||
/**
|
||||
* 流媒体节点
|
||||
*/
|
||||
private MediaServer mediaServer;
|
||||
/**
|
||||
* 协议
|
||||
*/
|
||||
private String schema;
|
||||
|
||||
/**
|
||||
* 流信息
|
||||
*/
|
||||
private MediaInfo mediaInfo;
|
||||
|
||||
/**
|
||||
* 录像信息
|
||||
*/
|
||||
private RecordInfo recordInfo;
|
||||
|
||||
@Schema(description = "推流的额外参数")
|
||||
private String params;
|
||||
public static HookData getInstance(MediaEvent mediaEvent) {
|
||||
HookData hookData = new HookData();
|
||||
if (mediaEvent instanceof MediaPublishEvent) {
|
||||
MediaPublishEvent event = (MediaPublishEvent) mediaEvent;
|
||||
hookData.setApp(event.getApp());
|
||||
hookData.setStream(event.getStream());
|
||||
hookData.setSchema(event.getSchema());
|
||||
hookData.setMediaServer(event.getMediaServer());
|
||||
hookData.setParams(event.getParams());
|
||||
}else if (mediaEvent instanceof MediaArrivalEvent) {
|
||||
MediaArrivalEvent event = (MediaArrivalEvent) mediaEvent;
|
||||
hookData.setApp(event.getApp());
|
||||
hookData.setStream(event.getStream());
|
||||
hookData.setSchema(event.getSchema());
|
||||
hookData.setMediaServer(event.getMediaServer());
|
||||
hookData.setMediaInfo(event.getMediaInfo());
|
||||
}else if (mediaEvent instanceof MediaRecordMp4Event) {
|
||||
MediaRecordMp4Event event = (MediaRecordMp4Event) mediaEvent;
|
||||
hookData.setApp(event.getApp());
|
||||
hookData.setStream(event.getStream());
|
||||
hookData.setSchema(event.getSchema());
|
||||
hookData.setMediaServer(event.getMediaServer());
|
||||
hookData.setRecordInfo(event.getRecordInfo());
|
||||
}else {
|
||||
hookData.setApp(mediaEvent.getApp());
|
||||
hookData.setStream(mediaEvent.getStream());
|
||||
hookData.setSchema(mediaEvent.getSchema());
|
||||
hookData.setMediaServer(mediaEvent.getMediaServer());
|
||||
}
|
||||
return hookData;
|
||||
}
|
||||
|
||||
public String getApp() {
|
||||
return app;
|
||||
}
|
||||
|
||||
public void setApp(String app) {
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
public String getStream() {
|
||||
return stream;
|
||||
}
|
||||
|
||||
public void setStream(String stream) {
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
public MediaServer getMediaServer() {
|
||||
return mediaServer;
|
||||
}
|
||||
|
||||
public void setMediaServer(MediaServer mediaServer) {
|
||||
this.mediaServer = mediaServer;
|
||||
}
|
||||
|
||||
public String getSchema() {
|
||||
return schema;
|
||||
}
|
||||
|
||||
public void setSchema(String schema) {
|
||||
this.schema = schema;
|
||||
}
|
||||
|
||||
public MediaInfo getMediaInfo() {
|
||||
return mediaInfo;
|
||||
}
|
||||
|
||||
public void setMediaInfo(MediaInfo mediaInfo) {
|
||||
this.mediaInfo = mediaInfo;
|
||||
}
|
||||
|
||||
public String getParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
public void setParams(String params) {
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
public RecordInfo getRecordInfo() {
|
||||
return recordInfo;
|
||||
}
|
||||
|
||||
public void setRecordInfo(RecordInfo recordInfo) {
|
||||
this.recordInfo = recordInfo;
|
||||
}
|
||||
}
|
||||
@@ -1,172 +1,105 @@
|
||||
package com.genersoft.iot.vmp.media.event.hook;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.genersoft.iot.vmp.media.event.MediaArrivalEvent;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import com.genersoft.iot.vmp.media.event.media.MediaArrivalEvent;
|
||||
import com.genersoft.iot.vmp.media.event.media.MediaDepartureEvent;
|
||||
import com.genersoft.iot.vmp.media.event.media.MediaEvent;
|
||||
import com.genersoft.iot.vmp.media.event.media.MediaPublishEvent;
|
||||
import org.mybatis.logging.Logger;
|
||||
import org.mybatis.logging.LoggerFactory;
|
||||
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.CollectionUtils;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* ZLMediaServer的hook事件订阅
|
||||
* zlm hook事件的参数
|
||||
* @author lin
|
||||
*/
|
||||
@Component
|
||||
public class HookSubscribe {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(HookSubscribe.class);
|
||||
/**
|
||||
* 订阅数据过期时间
|
||||
*/
|
||||
private final long subscribeExpire = 5 * 1000;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Event{
|
||||
void response(MediaServer mediaServerItem, HookParam hookParam);
|
||||
void response(HookData data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 流到来的处理
|
||||
*/
|
||||
@Async("taskExecutor")
|
||||
@org.springframework.context.event.EventListener
|
||||
@EventListener
|
||||
public void onApplicationEvent(MediaArrivalEvent event) {
|
||||
for (HookType hookType : allSubscribes.keySet()) {
|
||||
if (hookType.equals(HookType.on_stream_changed)) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Map<HookType, Map<IHookSubscribe, HookSubscribe.Event>> allSubscribes = new ConcurrentHashMap<>();
|
||||
|
||||
public void addSubscribe(IHookSubscribe hookSubscribe, HookSubscribe.Event event) {
|
||||
if (hookSubscribe.getExpires() == null) {
|
||||
// 默认5分钟过期
|
||||
Instant expiresInstant = Instant.now().plusSeconds(TimeUnit.MINUTES.toSeconds(5));
|
||||
hookSubscribe.setExpires(expiresInstant);
|
||||
}
|
||||
allSubscribes.computeIfAbsent(hookSubscribe.getHookType(), k -> new ConcurrentHashMap<>()).put(hookSubscribe, event);
|
||||
}
|
||||
|
||||
public HookSubscribe.Event sendNotify(HookType type, JSONObject hookResponse) {
|
||||
HookSubscribe.Event event= null;
|
||||
Map<IHookSubscribe, Event> eventMap = allSubscribes.get(type);
|
||||
if (eventMap == null) {
|
||||
return null;
|
||||
}
|
||||
for (IHookSubscribe key : eventMap.keySet()) {
|
||||
Boolean result = null;
|
||||
|
||||
for (String s : key.getContent().keySet()) {
|
||||
if (result == null) {
|
||||
result = key.getContent().getString(s).equals(hookResponse.getString(s));
|
||||
}else {
|
||||
if (key.getContent().getString(s) == null) {
|
||||
continue;
|
||||
}
|
||||
result = result && key.getContent().getString(s).equals(hookResponse.getString(s));
|
||||
}
|
||||
}
|
||||
if (null != result && result) {
|
||||
event = eventMap.get(key);
|
||||
}
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
public void removeSubscribe(IHookSubscribe hookSubscribe) {
|
||||
Map<IHookSubscribe, Event> eventMap = allSubscribes.get(hookSubscribe.getHookType());
|
||||
if (eventMap == null) {
|
||||
return;
|
||||
if ("rtsp".equals(event.getSchema())) {
|
||||
System.out.println("流到来的处理: " + allSubscribes.size());
|
||||
sendNotify(HookType.on_media_arrival, event);
|
||||
}
|
||||
|
||||
Set<Map.Entry<IHookSubscribe, Event>> entries = eventMap.entrySet();
|
||||
if (entries.size() > 0) {
|
||||
List<Map.Entry<IHookSubscribe, HookSubscribe.Event>> entriesToRemove = new ArrayList<>();
|
||||
for (Map.Entry<IHookSubscribe, HookSubscribe.Event> entry : entries) {
|
||||
JSONObject content = entry.getKey().getContent();
|
||||
if (content == null || content.size() == 0) {
|
||||
entriesToRemove.add(entry);
|
||||
continue;
|
||||
}
|
||||
Boolean result = null;
|
||||
for (String s : content.keySet()) {
|
||||
if (result == null) {
|
||||
result = content.getString(s).equals(hookSubscribe.getContent().getString(s));
|
||||
}else {
|
||||
if (content.getString(s) == null) {
|
||||
continue;
|
||||
}
|
||||
result = result && content.getString(s).equals(hookSubscribe.getContent().getString(s));
|
||||
}
|
||||
}
|
||||
if (result){
|
||||
entriesToRemove.add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
if (!CollectionUtils.isEmpty(entriesToRemove)) {
|
||||
for (Map.Entry<IHookSubscribe, HookSubscribe.Event> entry : entriesToRemove) {
|
||||
eventMap.remove(entry.getKey());
|
||||
}
|
||||
if (eventMap.size() == 0) {
|
||||
allSubscribes.remove(hookSubscribe.getHookType());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某个类型的所有的订阅
|
||||
* @param type
|
||||
* @return
|
||||
* 流结束事件
|
||||
*/
|
||||
public List<HookSubscribe.Event> getSubscribes(HookType type) {
|
||||
Map<IHookSubscribe, Event> eventMap = allSubscribes.get(type);
|
||||
if (eventMap == null) {
|
||||
return null;
|
||||
@Async("taskExecutor")
|
||||
@EventListener
|
||||
public void onApplicationEvent(MediaDepartureEvent event) {
|
||||
if ("rtsp".equals(event.getSchema())) {
|
||||
sendNotify(HookType.on_media_departure, event);
|
||||
}
|
||||
List<HookSubscribe.Event> result = new ArrayList<>();
|
||||
for (IHookSubscribe key : eventMap.keySet()) {
|
||||
result.add(eventMap.get(key));
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
/**
|
||||
* 推流鉴权事件
|
||||
*/
|
||||
@Async("taskExecutor")
|
||||
@EventListener
|
||||
public void onApplicationEvent(MediaPublishEvent event) {
|
||||
sendNotify(HookType.on_publish, event);
|
||||
}
|
||||
|
||||
public List<IHookSubscribe> getAll(){
|
||||
ArrayList<IHookSubscribe> result = new ArrayList<>();
|
||||
Collection<Map<IHookSubscribe, Event>> values = allSubscribes.values();
|
||||
for (Map<IHookSubscribe, Event> value : values) {
|
||||
result.addAll(value.keySet());
|
||||
private final Map<String, Event> allSubscribes = new ConcurrentHashMap<>();
|
||||
private final Map<String, Hook> allHook = new ConcurrentHashMap<>();
|
||||
|
||||
private void sendNotify(HookType hookType, MediaEvent event) {
|
||||
Hook paramHook = Hook.getInstance(hookType, event.getApp(), event.getStream(), event.getMediaServer().getId());
|
||||
Event hookSubscribeEvent = allSubscribes.get(paramHook.toString());
|
||||
if (hookSubscribeEvent != null) {
|
||||
HookData data = HookData.getInstance(event);
|
||||
hookSubscribeEvent.response(data);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void addSubscribe(Hook hook, HookSubscribe.Event event) {
|
||||
if (hook.getCreateTime() == null) {
|
||||
hook.setCreateTime(System.currentTimeMillis());
|
||||
}
|
||||
allSubscribes.put(hook.toString(), event);
|
||||
allHook.put(hook.toString(), hook);
|
||||
}
|
||||
|
||||
public void removeSubscribe(Hook hook) {
|
||||
allSubscribes.remove(hook.toString());
|
||||
allHook.remove(hook.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 对订阅数据进行过期清理
|
||||
*/
|
||||
// @Scheduled(cron="0 0/5 * * * ?") //每5分钟执行一次
|
||||
@Scheduled(fixedRate = 2 * 1000)
|
||||
@Scheduled(fixedRate=subscribeExpire) //每5分钟执行一次
|
||||
public void execute(){
|
||||
Instant instant = Instant.now().minusMillis(TimeUnit.MINUTES.toMillis(5));
|
||||
int total = 0;
|
||||
for (HookType hookType : allSubscribes.keySet()) {
|
||||
Map<IHookSubscribe, Event> hookSubscribeEventMap = allSubscribes.get(hookType);
|
||||
if (hookSubscribeEventMap.size() > 0) {
|
||||
for (IHookSubscribe hookSubscribe : hookSubscribeEventMap.keySet()) {
|
||||
if (hookSubscribe.getExpires().isBefore(instant)) {
|
||||
// 过期的
|
||||
hookSubscribeEventMap.remove(hookSubscribe);
|
||||
total ++;
|
||||
}
|
||||
}
|
||||
long expireTime = System.currentTimeMillis() - subscribeExpire;
|
||||
for (Hook hook : allHook.values()) {
|
||||
if (hook.getCreateTime() < expireTime) {
|
||||
allSubscribes.remove(hook.toString());
|
||||
allHook.remove(hook.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
package com.genersoft.iot.vmp.media.event.hook;
|
||||
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
|
||||
/**
|
||||
* hook 订阅工厂
|
||||
* @author lin
|
||||
*/
|
||||
public class HookSubscribeFactory {
|
||||
|
||||
public static HookSubscribeForStreamChange on_stream_changed(String app, String stream, boolean regist, String scheam, String mediaServerId) {
|
||||
HookSubscribeForStreamChange hookSubscribe = new HookSubscribeForStreamChange();
|
||||
JSONObject subscribeKey = new com.alibaba.fastjson2.JSONObject();
|
||||
subscribeKey.put("app", app);
|
||||
subscribeKey.put("stream", stream);
|
||||
subscribeKey.put("regist", regist);
|
||||
if (scheam != null) {
|
||||
subscribeKey.put("schema", scheam);
|
||||
}
|
||||
subscribeKey.put("mediaServerId", mediaServerId);
|
||||
hookSubscribe.setContent(subscribeKey);
|
||||
|
||||
return hookSubscribe;
|
||||
}
|
||||
|
||||
public static HookSubscribeForRtpServerTimeout on_rtp_server_timeout(String stream, String ssrc, String mediaServerId) {
|
||||
HookSubscribeForRtpServerTimeout hookSubscribe = new HookSubscribeForRtpServerTimeout();
|
||||
JSONObject subscribeKey = new com.alibaba.fastjson2.JSONObject();
|
||||
subscribeKey.put("stream_id", stream);
|
||||
subscribeKey.put("ssrc", ssrc);
|
||||
subscribeKey.put("mediaServerId", mediaServerId);
|
||||
hookSubscribe.setContent(subscribeKey);
|
||||
return hookSubscribe;
|
||||
}
|
||||
|
||||
public static HookSubscribeForStreamPush on_publish(String app, String stream, String scheam, String mediaServerId) {
|
||||
HookSubscribeForStreamPush hookSubscribe = new HookSubscribeForStreamPush();
|
||||
JSONObject subscribeKey = new JSONObject();
|
||||
subscribeKey.put("app", app);
|
||||
subscribeKey.put("stream", stream);
|
||||
if (scheam != null) {
|
||||
subscribeKey.put("schema", scheam);
|
||||
}
|
||||
subscribeKey.put("mediaServerId", mediaServerId);
|
||||
hookSubscribe.setContent(subscribeKey);
|
||||
|
||||
return hookSubscribe;
|
||||
}
|
||||
|
||||
public static HookSubscribeForRecordMp4 on_record_mp4(String mediaServerId, String app, String stream) {
|
||||
HookSubscribeForRecordMp4 hookSubscribe = new HookSubscribeForRecordMp4();
|
||||
JSONObject subscribeKey = new com.alibaba.fastjson2.JSONObject();
|
||||
subscribeKey.put("app", app);
|
||||
subscribeKey.put("stream", stream);
|
||||
subscribeKey.put("mediaServerId", mediaServerId);
|
||||
hookSubscribe.setContent(subscribeKey);
|
||||
|
||||
return hookSubscribe;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package com.genersoft.iot.vmp.media.event.hook;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
/**
|
||||
* hook订阅-录像完成
|
||||
* @author lin
|
||||
*/
|
||||
public class HookSubscribeForRecordMp4 implements IHookSubscribe{
|
||||
|
||||
private HookType hookType = HookType.on_record_mp4;
|
||||
|
||||
private JSONObject content;
|
||||
|
||||
@JSONField(format="yyyy-MM-dd HH:mm:ss")
|
||||
private Instant expires;
|
||||
|
||||
@Override
|
||||
public HookType getHookType() {
|
||||
return hookType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(JSONObject content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant getExpires() {
|
||||
return expires;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExpires(Instant expires) {
|
||||
this.expires = expires;
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package com.genersoft.iot.vmp.media.event.hook;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
/**
|
||||
* hook订阅-收流超时
|
||||
* @author lin
|
||||
*/
|
||||
public class HookSubscribeForRtpServerTimeout implements IHookSubscribe{
|
||||
|
||||
private HookType hookType = HookType.on_rtp_server_timeout;
|
||||
|
||||
private JSONObject content;
|
||||
|
||||
@JSONField(format="yyyy-MM-dd HH:mm:ss")
|
||||
private Instant expires;
|
||||
|
||||
@Override
|
||||
public HookType getHookType() {
|
||||
return hookType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(JSONObject content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant getExpires() {
|
||||
return expires;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExpires(Instant expires) {
|
||||
this.expires = expires;
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package com.genersoft.iot.vmp.media.event.hook;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
/**
|
||||
* hook订阅-流变化
|
||||
* @author lin
|
||||
*/
|
||||
public class HookSubscribeForStreamChange implements IHookSubscribe{
|
||||
|
||||
private HookType hookType = HookType.on_stream_changed;
|
||||
|
||||
private JSONObject content;
|
||||
|
||||
@JSONField(format="yyyy-MM-dd HH:mm:ss")
|
||||
private Instant expires;
|
||||
|
||||
@Override
|
||||
public HookType getHookType() {
|
||||
return hookType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(JSONObject content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant getExpires() {
|
||||
return expires;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExpires(Instant expires) {
|
||||
this.expires = expires;
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package com.genersoft.iot.vmp.media.event.hook;
|
||||
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
/**
|
||||
* hook订阅-开始推流
|
||||
* @author lin
|
||||
*/
|
||||
public class HookSubscribeForStreamPush implements IHookSubscribe{
|
||||
|
||||
private HookType hookType = HookType.on_publish;
|
||||
|
||||
private JSONObject content;
|
||||
|
||||
private Instant expires;
|
||||
|
||||
@Override
|
||||
public HookType getHookType() {
|
||||
return hookType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(JSONObject content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant getExpires() {
|
||||
return expires;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExpires(Instant expires) {
|
||||
this.expires = expires;
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,6 @@ public enum HookType {
|
||||
on_publish,
|
||||
on_record_mp4,
|
||||
on_media_arrival,
|
||||
on_stream_changed,
|
||||
on_media_departure,
|
||||
on_rtp_server_timeout,
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
package com.genersoft.iot.vmp.media.event.hook;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
/**
|
||||
* zlm hook事件的参数
|
||||
* @author lin
|
||||
*/
|
||||
public interface IHookSubscribe {
|
||||
|
||||
/**
|
||||
* 获取hook类型
|
||||
* @return hook类型
|
||||
*/
|
||||
HookType getHookType();
|
||||
|
||||
/**
|
||||
* 获取hook的具体内容
|
||||
* @return hook的具体内容
|
||||
*/
|
||||
JSONObject getContent();
|
||||
|
||||
/**
|
||||
* 设置过期时间
|
||||
* @param instant 过期时间
|
||||
*/
|
||||
void setExpires(Instant instant);
|
||||
|
||||
/**
|
||||
* 获取过期时间
|
||||
* @return 过期时间
|
||||
*/
|
||||
Instant getExpires();
|
||||
}
|
||||
@@ -1,21 +1,20 @@
|
||||
package com.genersoft.iot.vmp.media.event;
|
||||
package com.genersoft.iot.vmp.media.event.media;
|
||||
|
||||
import com.genersoft.iot.vmp.media.bean.MediaInfo;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
/**
|
||||
* 流到来事件
|
||||
*/
|
||||
public class MediaArrivalEvent extends ApplicationEvent {
|
||||
public class MediaArrivalEvent extends MediaEvent {
|
||||
public MediaArrivalEvent(Object source) {
|
||||
super(source);
|
||||
}
|
||||
|
||||
public static MediaArrivalEvent getInstance(Object source, OnStreamChangedHookParam hookParam, MediaServer mediaServer){
|
||||
MediaArrivalEvent mediaArrivalEvent = new MediaArrivalEvent(source);
|
||||
mediaArrivalEvent.setMediaInfo(MediaInfo.getInstance(hookParam));
|
||||
mediaArrivalEvent.setMediaInfo(MediaInfo.getInstance(hookParam, mediaServer));
|
||||
mediaArrivalEvent.setApp(hookParam.getApp());
|
||||
mediaArrivalEvent.setStream(hookParam.getStream());
|
||||
mediaArrivalEvent.setMediaServer(mediaServer);
|
||||
@@ -26,14 +25,6 @@ public class MediaArrivalEvent extends ApplicationEvent {
|
||||
|
||||
private MediaInfo mediaInfo;
|
||||
|
||||
private String app;
|
||||
|
||||
private String stream;
|
||||
|
||||
private MediaServer mediaServer;
|
||||
|
||||
private String schema;
|
||||
|
||||
private String callId;
|
||||
|
||||
public MediaInfo getMediaInfo() {
|
||||
@@ -44,37 +35,6 @@ public class MediaArrivalEvent extends ApplicationEvent {
|
||||
this.mediaInfo = mediaInfo;
|
||||
}
|
||||
|
||||
public String getApp() {
|
||||
return app;
|
||||
}
|
||||
|
||||
public void setApp(String app) {
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
public String getStream() {
|
||||
return stream;
|
||||
}
|
||||
|
||||
public void setStream(String stream) {
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
public MediaServer getMediaServer() {
|
||||
return mediaServer;
|
||||
}
|
||||
|
||||
public void setMediaServer(MediaServer mediaServer) {
|
||||
this.mediaServer = mediaServer;
|
||||
}
|
||||
|
||||
public String getSchema() {
|
||||
return schema;
|
||||
}
|
||||
|
||||
public void setSchema(String schema) {
|
||||
this.schema = schema;
|
||||
}
|
||||
|
||||
public String getCallId() {
|
||||
return callId;
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.genersoft.iot.vmp.media.event.media;
|
||||
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
|
||||
|
||||
/**
|
||||
* 流离开事件
|
||||
*/
|
||||
public class MediaDepartureEvent extends MediaEvent {
|
||||
public MediaDepartureEvent(Object source) {
|
||||
super(source);
|
||||
}
|
||||
|
||||
public static MediaDepartureEvent getInstance(Object source, OnStreamChangedHookParam hookParam, MediaServer mediaServer){
|
||||
MediaDepartureEvent mediaDepartureEven = new MediaDepartureEvent(source);
|
||||
mediaDepartureEven.setApp(hookParam.getApp());
|
||||
mediaDepartureEven.setStream(hookParam.getStream());
|
||||
mediaDepartureEven.setSchema(hookParam.getSchema());
|
||||
mediaDepartureEven.setMediaServer(mediaServer);
|
||||
return mediaDepartureEven;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,16 @@
|
||||
package com.genersoft.iot.vmp.media.event;
|
||||
package com.genersoft.iot.vmp.media.event.media;
|
||||
|
||||
import com.genersoft.iot.vmp.media.bean.MediaInfo;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookListener;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
/**
|
||||
* 流离开事件
|
||||
* 流到来事件
|
||||
*/
|
||||
public class MediaDepartureEvent extends ApplicationEvent {
|
||||
public MediaDepartureEvent(Object source) {
|
||||
public class MediaEvent extends ApplicationEvent {
|
||||
|
||||
public MediaEvent(Object source) {
|
||||
super(source);
|
||||
}
|
||||
|
||||
@@ -22,14 +22,6 @@ public class MediaDepartureEvent extends ApplicationEvent {
|
||||
|
||||
private String schema;
|
||||
|
||||
public static MediaDepartureEvent getInstance(Object source, OnStreamChangedHookParam hookParam, MediaServer mediaServer){
|
||||
MediaDepartureEvent mediaDepartureEven = new MediaDepartureEvent(source);
|
||||
mediaDepartureEven.setApp(hookParam.getApp());
|
||||
mediaDepartureEven.setStream(hookParam.getStream());
|
||||
mediaDepartureEven.setSchema(hookParam.getSchema());
|
||||
mediaDepartureEven.setMediaServer(mediaServer);
|
||||
return mediaDepartureEven;
|
||||
}
|
||||
|
||||
public String getApp() {
|
||||
return app;
|
||||
@@ -62,4 +54,5 @@ public class MediaDepartureEvent extends ApplicationEvent {
|
||||
public void setSchema(String schema) {
|
||||
this.schema = schema;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.genersoft.iot.vmp.media.event.media;
|
||||
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamNotFoundHookParam;
|
||||
|
||||
/**
|
||||
* 流未找到
|
||||
*/
|
||||
public class MediaNotFoundEvent extends MediaEvent {
|
||||
public MediaNotFoundEvent(Object source) {
|
||||
super(source);
|
||||
}
|
||||
|
||||
public static MediaNotFoundEvent getInstance(Object source, OnStreamNotFoundHookParam hookParam, MediaServer mediaServer){
|
||||
MediaNotFoundEvent mediaDepartureEven = new MediaNotFoundEvent(source);
|
||||
mediaDepartureEven.setApp(hookParam.getApp());
|
||||
mediaDepartureEven.setStream(hookParam.getStream());
|
||||
mediaDepartureEven.setSchema(hookParam.getSchema());
|
||||
mediaDepartureEven.setMediaServer(mediaServer);
|
||||
return mediaDepartureEven;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.genersoft.iot.vmp.media.event.media;
|
||||
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnPublishHookParam;
|
||||
|
||||
/**
|
||||
* 推流鉴权事件
|
||||
*/
|
||||
public class MediaPublishEvent extends MediaEvent {
|
||||
public MediaPublishEvent(Object source) {
|
||||
super(source);
|
||||
}
|
||||
|
||||
public static MediaPublishEvent getInstance(Object source, OnPublishHookParam hookParam, MediaServer mediaServer){
|
||||
MediaPublishEvent mediaPublishEvent = new MediaPublishEvent(source);
|
||||
mediaPublishEvent.setApp(hookParam.getApp());
|
||||
mediaPublishEvent.setStream(hookParam.getStream());
|
||||
mediaPublishEvent.setMediaServer(mediaServer);
|
||||
mediaPublishEvent.setSchema(hookParam.getSchema());
|
||||
mediaPublishEvent.setParams(hookParam.getParams());
|
||||
return mediaPublishEvent;
|
||||
}
|
||||
|
||||
private String params;
|
||||
|
||||
public String getParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
public void setParams(String params) {
|
||||
this.params = params;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.genersoft.iot.vmp.media.event.media;
|
||||
|
||||
import com.genersoft.iot.vmp.media.bean.RecordInfo;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
|
||||
|
||||
/**
|
||||
* 录像文件生成事件
|
||||
*/
|
||||
public class MediaRecordMp4Event extends MediaEvent {
|
||||
public MediaRecordMp4Event(Object source) {
|
||||
super(source);
|
||||
}
|
||||
|
||||
private RecordInfo recordInfo;
|
||||
|
||||
public static MediaRecordMp4Event getInstance(Object source, OnRecordMp4HookParam hookParam, MediaServer mediaServer){
|
||||
MediaRecordMp4Event mediaRecordMp4Event = new MediaRecordMp4Event(source);
|
||||
mediaRecordMp4Event.setApp(hookParam.getApp());
|
||||
mediaRecordMp4Event.setStream(hookParam.getStream());
|
||||
RecordInfo recordInfo = RecordInfo.getInstance(hookParam);
|
||||
mediaRecordMp4Event.setRecordInfo(recordInfo);
|
||||
mediaRecordMp4Event.setMediaServer(mediaServer);
|
||||
return mediaRecordMp4Event;
|
||||
}
|
||||
|
||||
public RecordInfo getRecordInfo() {
|
||||
return recordInfo;
|
||||
}
|
||||
|
||||
public void setRecordInfo(RecordInfo recordInfo) {
|
||||
this.recordInfo = recordInfo;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.genersoft.iot.vmp.media.event.media;
|
||||
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
|
||||
|
||||
/**
|
||||
* RtpServer收流超时事件
|
||||
*/
|
||||
public class MediaRtpServerTimeoutEvent extends MediaEvent {
|
||||
public MediaRtpServerTimeoutEvent(Object source) {
|
||||
super(source);
|
||||
}
|
||||
|
||||
public static MediaRtpServerTimeoutEvent getInstance(Object source, OnStreamChangedHookParam hookParam, MediaServer mediaServer){
|
||||
MediaRtpServerTimeoutEvent mediaDepartureEven = new MediaRtpServerTimeoutEvent(source);
|
||||
mediaDepartureEven.setApp(hookParam.getApp());
|
||||
mediaDepartureEven.setStream(hookParam.getStream());
|
||||
mediaDepartureEven.setSchema(hookParam.getSchema());
|
||||
mediaDepartureEven.setMediaServer(mediaServer);
|
||||
return mediaDepartureEven;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.genersoft.iot.vmp.media.event;
|
||||
package com.genersoft.iot.vmp.media.event.mediaServer;
|
||||
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamNotFoundHookParam;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.genersoft.iot.vmp.media.event;
|
||||
package com.genersoft.iot.vmp.media.event.mediaServer;
|
||||
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServer;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.genersoft.iot.vmp.media.event;
|
||||
package com.genersoft.iot.vmp.media.event.mediaServer;
|
||||
|
||||
/**
|
||||
* zlm在线事件
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.genersoft.iot.vmp.media.event;
|
||||
package com.genersoft.iot.vmp.media.event.mediaServer;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
package com.genersoft.iot.vmp.media.event;
|
||||
|
||||
import com.genersoft.iot.vmp.media.event.MediaServerEventAbstract;
|
||||
package com.genersoft.iot.vmp.media.event.mediaServer;
|
||||
|
||||
/**
|
||||
* zlm离线事件类
|
||||
@@ -1,6 +1,4 @@
|
||||
package com.genersoft.iot.vmp.media.event;
|
||||
|
||||
import com.genersoft.iot.vmp.media.event.MediaServerEventAbstract;
|
||||
package com.genersoft.iot.vmp.media.event.mediaServer;
|
||||
|
||||
/**
|
||||
* zlm在线事件
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.genersoft.iot.vmp.media.event;
|
||||
package com.genersoft.iot.vmp.media.event.mediaServer;
|
||||
|
||||
import com.genersoft.iot.vmp.service.IPlayService;
|
||||
import com.genersoft.iot.vmp.service.IStreamProxyService;
|
||||
@@ -104,4 +104,36 @@ public interface IMediaServerService {
|
||||
|
||||
Map<String, String> getFFmpegCMDs(MediaServer mediaServer);
|
||||
|
||||
/**
|
||||
* 根据应用名和流ID获取播放地址, 通过zlm接口检查是否存在
|
||||
* @param app
|
||||
* @param stream
|
||||
* @return
|
||||
*/
|
||||
StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId,String addr, boolean authority);
|
||||
|
||||
|
||||
/**
|
||||
* 根据应用名和流ID获取播放地址, 通过zlm接口检查是否存在, 返回的ip使用远程访问ip,适用与zlm与wvp在一台主机的情况
|
||||
* @param app
|
||||
* @param stream
|
||||
* @return
|
||||
*/
|
||||
StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, boolean authority);
|
||||
|
||||
/**
|
||||
* 根据应用名和流ID获取播放地址, 只是地址拼接
|
||||
* @param app
|
||||
* @param stream
|
||||
* @return
|
||||
*/
|
||||
StreamInfo getStreamInfoByAppAndStream(MediaServer mediaServerItem, String app, String stream, MediaInfo mediaInfo, String callId);
|
||||
|
||||
/**
|
||||
* 根据应用名和流ID获取播放地址, 只是地址拼接,返回的ip使用远程访问ip,适用与zlm与wvp在一台主机的情况
|
||||
* @param app
|
||||
* @param stream
|
||||
* @return
|
||||
*/
|
||||
StreamInfo getStreamInfoByAppAndStream(MediaServer mediaServerItem, String app, String stream, MediaInfo mediaInfo, String addr, String callId, boolean isPlay);
|
||||
}
|
||||
|
||||
@@ -4,17 +4,19 @@ import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.genersoft.iot.vmp.common.CommonCallback;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||
import com.genersoft.iot.vmp.conf.MediaConfig;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
|
||||
import com.genersoft.iot.vmp.media.bean.MediaInfo;
|
||||
import com.genersoft.iot.vmp.media.event.MediaArrivalEvent;
|
||||
import com.genersoft.iot.vmp.media.event.MediaDepartureEvent;
|
||||
import com.genersoft.iot.vmp.media.event.MediaServerChangeEvent;
|
||||
import com.genersoft.iot.vmp.media.event.MediaServerDeleteEvent;
|
||||
import com.genersoft.iot.vmp.media.event.media.MediaArrivalEvent;
|
||||
import com.genersoft.iot.vmp.media.event.media.MediaDepartureEvent;
|
||||
import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerChangeEvent;
|
||||
import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerDeleteEvent;
|
||||
import com.genersoft.iot.vmp.media.service.IMediaNodeServerService;
|
||||
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.StreamAuthorityInfo;
|
||||
import com.genersoft.iot.vmp.service.IInviteStreamService;
|
||||
import com.genersoft.iot.vmp.service.bean.MediaServerLoad;
|
||||
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
||||
@@ -74,6 +76,10 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
@Autowired
|
||||
private ApplicationEventPublisher applicationEventPublisher;
|
||||
|
||||
@Autowired
|
||||
private MediaConfig mediaConfig;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 流到来的处理
|
||||
@@ -714,4 +720,63 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
}
|
||||
return mediaNodeServerService.getFFmpegCMDs(mediaServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StreamInfo getStreamInfoByAppAndStream(MediaServer mediaServerItem, String app, String stream, MediaInfo mediaInfo, String callId) {
|
||||
return getStreamInfoByAppAndStream(mediaServerItem, app, stream, mediaInfo, null, callId, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, String addr, boolean authority) {
|
||||
StreamInfo streamInfo = null;
|
||||
if (mediaServerId == null) {
|
||||
mediaServerId = mediaConfig.getId();
|
||||
}
|
||||
MediaServer mediaInfo = getOne(mediaServerId);
|
||||
if (mediaInfo == null) {
|
||||
return null;
|
||||
}
|
||||
String calld = null;
|
||||
StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(app, stream);
|
||||
if (streamAuthorityInfo != null) {
|
||||
calld = streamAuthorityInfo.getCallId();
|
||||
}
|
||||
List<StreamInfo> streamInfoList = getMediaList(mediaInfo, app, stream, calld);
|
||||
if (streamInfoList.isEmpty()) {
|
||||
return null;
|
||||
}else {
|
||||
return streamInfoList.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, boolean authority) {
|
||||
return getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, null, authority);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StreamInfo getStreamInfoByAppAndStream(MediaServer mediaServer, String app, String stream, MediaInfo mediaInfo, String addr, String callId, boolean isPlay) {
|
||||
StreamInfo streamInfoResult = new StreamInfo();
|
||||
streamInfoResult.setStream(stream);
|
||||
streamInfoResult.setApp(app);
|
||||
if (addr == null) {
|
||||
addr = mediaServer.getStreamIp();
|
||||
}
|
||||
|
||||
streamInfoResult.setIp(addr);
|
||||
streamInfoResult.setMediaServerId(mediaServer.getId());
|
||||
String callIdParam = ObjectUtils.isEmpty(callId)?"":"?callId=" + callId;
|
||||
streamInfoResult.setRtmp(addr, mediaServer.getRtmpPort(),mediaServer.getRtmpSSlPort(), app, stream, callIdParam);
|
||||
streamInfoResult.setRtsp(addr, mediaServer.getRtspPort(),mediaServer.getRtspSSLPort(), app, stream, callIdParam);
|
||||
streamInfoResult.setFlv(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app, stream, callIdParam);
|
||||
streamInfoResult.setFmp4(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app, stream, callIdParam);
|
||||
streamInfoResult.setHls(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app, stream, callIdParam);
|
||||
streamInfoResult.setTs(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app, stream, callIdParam);
|
||||
streamInfoResult.setRtc(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app, stream, callIdParam, isPlay);
|
||||
|
||||
streamInfoResult.setMediaInfo(mediaInfo);
|
||||
return streamInfoResult;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,9 +11,10 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||
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.bean.ResultForOnPublish;
|
||||
import com.genersoft.iot.vmp.media.event.*;
|
||||
import com.genersoft.iot.vmp.media.event.hook.HookSubscribe;
|
||||
import com.genersoft.iot.vmp.media.event.hook.HookType;
|
||||
import com.genersoft.iot.vmp.media.event.media.*;
|
||||
import com.genersoft.iot.vmp.media.event.mediaServer.MediaSendRtpStoppedEvent;
|
||||
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;
|
||||
@@ -175,13 +176,6 @@ public class ZLMHttpHookListener {
|
||||
return new HookResultForOnPublish(200, "success");
|
||||
}
|
||||
|
||||
taskExecutor.execute(() -> {
|
||||
HookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_publish, json);
|
||||
if (subscribe != null) {
|
||||
subscribe.response(mediaServer, param);
|
||||
}
|
||||
});
|
||||
|
||||
ResultForOnPublish resultForOnPublish = mediaService.authenticatePublish(mediaServer, param.getApp(), param.getStream(), param.getParams());
|
||||
if (resultForOnPublish != null) {
|
||||
HookResultForOnPublish successResult = HookResultForOnPublish.getInstance(resultForOnPublish);
|
||||
@@ -316,19 +310,12 @@ public class ZLMHttpHookListener {
|
||||
MediaServer mediaServerItem = mediaServerService.getOne(param.getMediaServerId());
|
||||
if (mediaServerItem != null) {
|
||||
event.setMediaServer(mediaServerItem);
|
||||
event.setApp("rtp");
|
||||
applicationEventPublisher.publishEvent(event);
|
||||
}
|
||||
}catch (Exception e) {
|
||||
logger.info("[ZLM-HOOK-rtpServer收流超时] 发送通知失败 ", e);
|
||||
}
|
||||
taskExecutor.execute(() -> {
|
||||
List<HookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_rtp_server_timeout);
|
||||
if (subscribes != null && !subscribes.isEmpty()) {
|
||||
for (HookSubscribe.Event subscribe : subscribes) {
|
||||
subscribe.response(null, param);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return HookResult.SUCCESS();
|
||||
}
|
||||
@@ -341,16 +328,16 @@ public class ZLMHttpHookListener {
|
||||
public HookResult onRecordMp4(HttpServletRequest request, @RequestBody OnRecordMp4HookParam param) {
|
||||
logger.info("[ZLM HOOK] 录像完成事件:{}->{}", param.getMediaServerId(), param.getFile_path());
|
||||
|
||||
taskExecutor.execute(() -> {
|
||||
List<HookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_record_mp4);
|
||||
if (subscribes != null && !subscribes.isEmpty()) {
|
||||
for (HookSubscribe.Event subscribe : subscribes) {
|
||||
subscribe.response(null, param);
|
||||
}
|
||||
try {
|
||||
MediaRecordMp4Event event = new MediaRecordMp4Event(this);
|
||||
MediaServer mediaServerItem = mediaServerService.getOne(param.getMediaServerId());
|
||||
if (mediaServerItem != null) {
|
||||
event.setMediaServer(mediaServerItem);
|
||||
applicationEventPublisher.publishEvent(event);
|
||||
}
|
||||
cloudRecordService.addRecord(param);
|
||||
|
||||
});
|
||||
}catch (Exception e) {
|
||||
logger.info("[ZLM-HOOK-rtpServer收流超时] 发送通知失败 ", e);
|
||||
}
|
||||
|
||||
return HookResult.SUCCESS();
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ public class ZLMMediaNodeServerService implements IMediaNodeServerService {
|
||||
return null;
|
||||
}
|
||||
JSONObject mediaJSON = data.getJSONObject(0);
|
||||
MediaInfo mediaInfo = MediaInfo.getInstance(mediaJSON);
|
||||
MediaInfo mediaInfo = MediaInfo.getInstance(mediaJSON, mediaServer);
|
||||
StreamInfo streamInfo = getStreamInfoByAppAndStream(mediaServer, app, stream, mediaInfo, callId, true);
|
||||
if (streamInfo != null) {
|
||||
streamInfoList.add(streamInfo);
|
||||
@@ -207,7 +207,7 @@ public class ZLMMediaNodeServerService implements IMediaNodeServerService {
|
||||
if (jsonObject.getInteger("code") != 0) {
|
||||
return null;
|
||||
}
|
||||
return MediaInfo.getInstance(jsonObject);
|
||||
return MediaInfo.getInstance(jsonObject, mediaServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,8 +5,8 @@ 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.event.MediaServerChangeEvent;
|
||||
import com.genersoft.iot.vmp.media.event.MediaServerDeleteEvent;
|
||||
import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerChangeEvent;
|
||||
import com.genersoft.iot.vmp.media.event.mediaServer.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;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.genersoft.iot.vmp.media.zlm.dto;
|
||||
|
||||
import com.genersoft.iot.vmp.media.event.MediaArrivalEvent;
|
||||
import com.genersoft.iot.vmp.media.event.media.MediaArrivalEvent;
|
||||
|
||||
/**
|
||||
* 流的鉴权信息
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.genersoft.iot.vmp.media.zlm.dto;
|
||||
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.GbStream;
|
||||
import com.genersoft.iot.vmp.media.event.MediaArrivalEvent;
|
||||
import com.genersoft.iot.vmp.media.event.media.MediaArrivalEvent;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
Reference in New Issue
Block a user