合并主线
This commit is contained in:
@@ -56,4 +56,35 @@ public interface IDeviceChannelService {
|
||||
* 查询通道所属的设备
|
||||
*/
|
||||
List<Device> getDeviceByChannelId(String channelId);
|
||||
|
||||
/**
|
||||
* 批量删除通道
|
||||
* @param deleteChannelList 待删除的通道列表
|
||||
*/
|
||||
int deleteChannels(List<DeviceChannel> deleteChannelList);
|
||||
|
||||
/**
|
||||
* 批量上线
|
||||
*/
|
||||
int channelsOnline(List<DeviceChannel> channels);
|
||||
|
||||
/**
|
||||
* 批量下线
|
||||
*/
|
||||
int channelsOffline(List<DeviceChannel> channels);
|
||||
|
||||
/**
|
||||
* 获取一个通道
|
||||
*/
|
||||
DeviceChannel getOne(String deviceId, String channelId);
|
||||
|
||||
/**
|
||||
* 直接批量更新通道
|
||||
*/
|
||||
void batchUpdateChannel(List<DeviceChannel> channels);
|
||||
|
||||
/**
|
||||
* 直接批量添加
|
||||
*/
|
||||
void batchAddChannel(List<DeviceChannel> deviceChannels);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.genersoft.iot.vmp.service;
|
||||
|
||||
import com.genersoft.iot.vmp.common.InviteInfo;
|
||||
import com.genersoft.iot.vmp.common.InviteSessionType;
|
||||
import com.genersoft.iot.vmp.service.bean.InviteErrorCallback;
|
||||
|
||||
/**
|
||||
* 记录国标点播的状态,包括实时预览,下载,录像回放
|
||||
*/
|
||||
public interface IInviteStreamService {
|
||||
|
||||
/**
|
||||
* 更新点播的状态信息
|
||||
*/
|
||||
void updateInviteInfo(InviteInfo inviteInfo);
|
||||
|
||||
/**
|
||||
* 获取点播的状态信息
|
||||
*/
|
||||
InviteInfo getInviteInfo(InviteSessionType type,
|
||||
String deviceId,
|
||||
String channelId,
|
||||
String stream);
|
||||
|
||||
/**
|
||||
* 移除点播的状态信息
|
||||
*/
|
||||
void removeInviteInfo(InviteSessionType type,
|
||||
String deviceId,
|
||||
String channelId,
|
||||
String stream);
|
||||
/**
|
||||
* 移除点播的状态信息
|
||||
*/
|
||||
void removeInviteInfo(InviteInfo inviteInfo);
|
||||
/**
|
||||
* 移除点播的状态信息
|
||||
*/
|
||||
void removeInviteInfoByDeviceAndChannel(InviteSessionType inviteSessionType, String deviceId, String channelId);
|
||||
|
||||
/**
|
||||
* 获取点播的状态信息
|
||||
*/
|
||||
InviteInfo getInviteInfoByDeviceAndChannel(InviteSessionType type,
|
||||
String deviceId,
|
||||
String channelId);
|
||||
|
||||
/**
|
||||
* 获取点播的状态信息
|
||||
*/
|
||||
InviteInfo getInviteInfoByStream(InviteSessionType type, String stream);
|
||||
|
||||
|
||||
/**
|
||||
* 添加一个invite回调
|
||||
*/
|
||||
void once(InviteSessionType type, String deviceId, String channelId, String stream, InviteErrorCallback<Object> callback);
|
||||
|
||||
/**
|
||||
* 调用一个invite回调
|
||||
*/
|
||||
void call(InviteSessionType type, String deviceId, String channelId, String stream, int code, String msg, Object data);
|
||||
|
||||
/**
|
||||
* 清空一个设备的所有invite信息
|
||||
*/
|
||||
void clearInviteInfo(String deviceId);
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.genersoft.iot.vmp.service;
|
||||
|
||||
import com.genersoft.iot.vmp.common.CommonCallback;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.ServerKeepaliveData;
|
||||
@@ -43,14 +44,16 @@ public interface IMediaServerService {
|
||||
|
||||
void updateVmServer(List<MediaServerItem> mediaServerItemList);
|
||||
|
||||
SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean ssrcCheck, boolean isPlayback);
|
||||
|
||||
SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback);
|
||||
SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String presetSsrc, boolean ssrcCheck,
|
||||
boolean isPlayback, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode);
|
||||
|
||||
SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback, Integer port, Boolean onlyAuto);
|
||||
|
||||
void closeRTPServer(MediaServerItem mediaServerItem, String streamId);
|
||||
|
||||
void closeRTPServer(MediaServerItem mediaServerItem, String streamId, CommonCallback<Boolean> callback);
|
||||
Boolean updateRtpServerSSRC(MediaServerItem mediaServerItem, String streamId, String ssrc);
|
||||
|
||||
void closeRTPServer(String mediaServerId, String streamId);
|
||||
|
||||
void clearRTPServer(MediaServerItem mediaServerItem);
|
||||
|
||||
@@ -3,12 +3,11 @@ package com.genersoft.iot.vmp.service;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.conf.exception.ServiceException;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.service.bean.InviteTimeOutCallback;
|
||||
import com.genersoft.iot.vmp.service.bean.PlayBackCallback;
|
||||
import com.genersoft.iot.vmp.service.bean.InviteErrorCallback;
|
||||
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult;
|
||||
import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent;
|
||||
@@ -25,12 +24,11 @@ import java.util.Map;
|
||||
*/
|
||||
public interface IPlayService {
|
||||
|
||||
void onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId);
|
||||
|
||||
void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
|
||||
ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent,
|
||||
InviteTimeOutCallback timeoutCallback);
|
||||
void play(MediaServerItem mediaServerItem, String deviceId, String channelId, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent, Runnable timeoutCallback);
|
||||
InviteErrorCallback<Object> callback);
|
||||
SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, InviteErrorCallback<Object> callback);
|
||||
|
||||
StreamInfo onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId);
|
||||
|
||||
MediaServerItem getNewMediaServerItem(Device device);
|
||||
|
||||
@@ -39,15 +37,13 @@ public interface IPlayService {
|
||||
*/
|
||||
MediaServerItem getNewMediaServerItemHasAssist(Device device);
|
||||
|
||||
void onPublishHandlerForDownload(InviteStreamInfo inviteStreamInfo, String deviceId, String channelId, String toString);
|
||||
|
||||
void playBack(String deviceId, String channelId, String startTime, String endTime, InviteStreamCallback infoCallBack, PlayBackCallback playBackCallback);
|
||||
void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack);
|
||||
void playBack(String deviceId, String channelId, String startTime, String endTime, InviteErrorCallback<Object> callback);
|
||||
void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, InviteErrorCallback<Object> callback);
|
||||
|
||||
void zlmServerOffline(String mediaServerId);
|
||||
|
||||
void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback playBackCallback);
|
||||
void download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack);
|
||||
void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteErrorCallback<Object> callback);
|
||||
void download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteErrorCallback<Object> callback);
|
||||
|
||||
StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream);
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.genersoft.iot.vmp.service.bean;
|
||||
|
||||
public interface InviteErrorCallback<T> {
|
||||
|
||||
void run(int code, String msg, T data);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.genersoft.iot.vmp.service.bean;
|
||||
|
||||
/**
|
||||
* 全局错误码
|
||||
*/
|
||||
public enum InviteErrorCode {
|
||||
SUCCESS(0, "成功"),
|
||||
ERROR_FOR_SIGNALLING_TIMEOUT(-1, "信令超时"),
|
||||
ERROR_FOR_STREAM_TIMEOUT(-2, "收流超时"),
|
||||
ERROR_FOR_RESOURCE_EXHAUSTION(-3, "资源耗尽"),
|
||||
ERROR_FOR_CATCH_DATA(-4, "缓存数据异常"),
|
||||
ERROR_FOR_SIGNALLING_ERROR(-5, "收到信令错误"),
|
||||
ERROR_FOR_STREAM_PARSING_EXCEPTIONS(-6, "流地址解析错误"),
|
||||
ERROR_FOR_SDP_PARSING_EXCEPTIONS(-7, "SDP信息解析失败"),
|
||||
ERROR_FOR_SSRC_UNAVAILABLE(-8, "SSRC不可用"),
|
||||
ERROR_FOR_RESET_SSRC(-9, "重新设置收流信息失败"),
|
||||
ERROR_FOR_SIP_SENDING_FAILED(-10, "命令发送失败"),
|
||||
ERROR_FOR_ASSIST_NOT_READY(-11, "没有可用的assist服务"),
|
||||
ERROR_FOR_PARAMETER_ERROR(-13, "参数异常");
|
||||
|
||||
private final int code;
|
||||
private final String msg;
|
||||
|
||||
InviteErrorCode(int code, String msg) {
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
package com.genersoft.iot.vmp.service.impl;
|
||||
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.common.InviteInfo;
|
||||
import com.genersoft.iot.vmp.common.InviteSessionType;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.Coordtransform;
|
||||
import com.genersoft.iot.vmp.service.IDeviceChannelService;
|
||||
import com.genersoft.iot.vmp.service.IInviteStreamService;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
|
||||
import com.genersoft.iot.vmp.storager.dao.DeviceMapper;
|
||||
@@ -32,6 +34,9 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
|
||||
@Autowired
|
||||
private IRedisCatchStorage redisCatchStorage;
|
||||
|
||||
@Autowired
|
||||
private IInviteStreamService inviteStreamService;
|
||||
|
||||
@Autowired
|
||||
private DeviceChannelMapper channelMapper;
|
||||
|
||||
@@ -45,6 +50,8 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
|
||||
device = deviceMapper.getDeviceByDeviceId(deviceChannel.getDeviceId());
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ("WGS84".equals(device.getGeoCoordSys())) {
|
||||
deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude());
|
||||
deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude());
|
||||
@@ -76,9 +83,10 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
|
||||
public void updateChannel(String deviceId, DeviceChannel channel) {
|
||||
String channelId = channel.getChannelId();
|
||||
channel.setDeviceId(deviceId);
|
||||
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
|
||||
if (streamInfo != null) {
|
||||
channel.setStreamId(streamInfo.getStream());
|
||||
// StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
|
||||
InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId);
|
||||
if (inviteInfo != null && inviteInfo.getStreamInfo() != null) {
|
||||
channel.setStreamId(inviteInfo.getStreamInfo().getStream());
|
||||
}
|
||||
String now = DateUtil.getNow();
|
||||
channel.setUpdateTime(now);
|
||||
@@ -104,9 +112,9 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
|
||||
if (channelList.size() == 0) {
|
||||
for (DeviceChannel channel : channels) {
|
||||
channel.setDeviceId(deviceId);
|
||||
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channel.getChannelId());
|
||||
if (streamInfo != null) {
|
||||
channel.setStreamId(streamInfo.getStream());
|
||||
InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channel.getChannelId());
|
||||
if (inviteInfo != null && inviteInfo.getStreamInfo() != null) {
|
||||
channel.setStreamId(inviteInfo.getStreamInfo().getStream());
|
||||
}
|
||||
String now = DateUtil.getNow();
|
||||
channel.setUpdateTime(now);
|
||||
@@ -120,9 +128,9 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
|
||||
}
|
||||
for (DeviceChannel channel : channels) {
|
||||
channel.setDeviceId(deviceId);
|
||||
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channel.getChannelId());
|
||||
if (streamInfo != null) {
|
||||
channel.setStreamId(streamInfo.getStream());
|
||||
InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channel.getChannelId());
|
||||
if (inviteInfo != null && inviteInfo.getStreamInfo() != null) {
|
||||
channel.setStreamId(inviteInfo.getStreamInfo().getStream());
|
||||
}
|
||||
String now = DateUtil.getNow();
|
||||
channel.setUpdateTime(now);
|
||||
@@ -207,6 +215,47 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
|
||||
|
||||
@Override
|
||||
public List<Device> getDeviceByChannelId(String channelId) {
|
||||
|
||||
return channelMapper.getDeviceByChannelId(channelId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteChannels(List<DeviceChannel> deleteChannelList) {
|
||||
return channelMapper.batchDel(deleteChannelList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int channelsOnline(List<DeviceChannel> channels) {
|
||||
return channelMapper.batchOnline(channels);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int channelsOffline(List<DeviceChannel> channels) {
|
||||
return channelMapper.batchOffline(channels);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceChannel getOne(String deviceId, String channelId){
|
||||
return channelMapper.queryChannel(deviceId, channelId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void batchUpdateChannel(List<DeviceChannel> channels) {
|
||||
channelMapper.batchUpdate(channels);
|
||||
for (DeviceChannel channel : channels) {
|
||||
if (channel.getParentId() != null) {
|
||||
channelMapper.updateChannelSubCount(channel.getDeviceId(), channel.getParentId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void batchAddChannel(List<DeviceChannel> channels) {
|
||||
channelMapper.batchAdd(channels);
|
||||
for (DeviceChannel channel : channels) {
|
||||
if (channel.getParentId() != null) {
|
||||
channelMapper.updateChannelSubCount(channel.getDeviceId(), channel.getParentId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.service.IDeviceChannelService;
|
||||
import com.genersoft.iot.vmp.service.IDeviceService;
|
||||
import com.genersoft.iot.vmp.service.IInviteStreamService;
|
||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
|
||||
@@ -59,6 +60,9 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
@Autowired
|
||||
private IRedisCatchStorage redisCatchStorage;
|
||||
|
||||
@Autowired
|
||||
private IInviteStreamService inviteStreamService;
|
||||
|
||||
@Autowired
|
||||
private DeviceMapper deviceMapper;
|
||||
|
||||
@@ -104,7 +108,7 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
String now = DateUtil.getNow();
|
||||
if (deviceInRedis != null && deviceInDb == null) {
|
||||
// redis 存在脏数据
|
||||
redisCatchStorage.clearCatchByDeviceId(device.getDeviceId());
|
||||
inviteStreamService.clearInviteInfo(device.getDeviceId());
|
||||
}
|
||||
device.setUpdateTime(now);
|
||||
if (device.getKeepaliveIntervalTime() == 0) {
|
||||
@@ -172,6 +176,11 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + device.getDeviceId();
|
||||
// 如果第一次注册那么必须在60 * 3时间内收到一个心跳,否则设备离线
|
||||
dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId(), "首次注册后未能收到心跳"), device.getKeepaliveIntervalTime() * 1000 * 3);
|
||||
if (userSetting.getDeviceStatusNotify()) {
|
||||
// 发送redis消息
|
||||
redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), null, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -200,6 +209,11 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
// 移除订阅
|
||||
removeCatalogSubscribe(device);
|
||||
removeMobilePositionSubscribe(device);
|
||||
if (userSetting.getDeviceStatusNotify()) {
|
||||
// 发送redis消息
|
||||
redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), null, false);
|
||||
}
|
||||
|
||||
List<AudioBroadcastCatch> audioBroadcastCatches = audioBroadcastManager.get(deviceId);
|
||||
if (audioBroadcastCatches.size() > 0) {
|
||||
for (AudioBroadcastCatch audioBroadcastCatch : audioBroadcastCatches) {
|
||||
@@ -512,8 +526,10 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
node.setBasicData(channel);
|
||||
node.setParent(false);
|
||||
if (channel.getChannelId().length() > 8) {
|
||||
String gbCodeType = channel.getChannelId().substring(10, 13);
|
||||
node.setParent(gbCodeType.equals(ChannelIdType.BUSINESS_GROUP) || gbCodeType.equals(ChannelIdType.VIRTUAL_ORGANIZATION) );
|
||||
if (channel.getChannelId().length() > 13) {
|
||||
String gbCodeType = channel.getChannelId().substring(10, 13);
|
||||
node.setParent(gbCodeType.equals(ChannelIdType.BUSINESS_GROUP) || gbCodeType.equals(ChannelIdType.VIRTUAL_ORGANIZATION) );
|
||||
}
|
||||
}else {
|
||||
node.setParent(true);
|
||||
}
|
||||
@@ -669,4 +685,6 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
public List<Device> getAll() {
|
||||
return deviceMapper.getAll();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
package com.genersoft.iot.vmp.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.genersoft.iot.vmp.common.InviteInfo;
|
||||
import com.genersoft.iot.vmp.common.InviteSessionStatus;
|
||||
import com.genersoft.iot.vmp.common.InviteSessionType;
|
||||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||
import com.genersoft.iot.vmp.service.IInviteStreamService;
|
||||
import com.genersoft.iot.vmp.service.bean.InviteErrorCallback;
|
||||
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
@Service
|
||||
public class InviteStreamServiceImpl implements IInviteStreamService {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(InviteStreamServiceImpl.class);
|
||||
|
||||
private final Map<String, List<InviteErrorCallback<Object>>> inviteErrorCallbackMap = new ConcurrentHashMap<>();
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<Object, Object> redisTemplate;
|
||||
|
||||
@Override
|
||||
public void updateInviteInfo(InviteInfo inviteInfo) {
|
||||
if (inviteInfo == null || (inviteInfo.getDeviceId() == null || inviteInfo.getChannelId() == null)) {
|
||||
logger.warn("[更新Invite信息],参数不全: {}", JSON.toJSON(inviteInfo));
|
||||
return;
|
||||
}
|
||||
InviteInfo inviteInfoForUpdate = null;
|
||||
|
||||
if (InviteSessionStatus.ready == inviteInfo.getStatus()) {
|
||||
if (inviteInfo.getDeviceId() == null
|
||||
|| inviteInfo.getChannelId() == null
|
||||
|| inviteInfo.getType() == null
|
||||
|| inviteInfo.getStream() == null
|
||||
) {
|
||||
return;
|
||||
}
|
||||
inviteInfoForUpdate = inviteInfo;
|
||||
} else {
|
||||
InviteInfo inviteInfoInRedis = getInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId(),
|
||||
inviteInfo.getChannelId(), inviteInfo.getStream());
|
||||
if (inviteInfoInRedis == null) {
|
||||
logger.warn("[更新Invite信息],未从缓存中读取到Invite信息: deviceId: {}, channel: {}, stream: {}",
|
||||
inviteInfo.getDeviceId(), inviteInfo.getChannelId(), inviteInfo.getStream());
|
||||
return;
|
||||
}
|
||||
if (inviteInfo.getStreamInfo() != null) {
|
||||
inviteInfoInRedis.setStreamInfo(inviteInfo.getStreamInfo());
|
||||
}
|
||||
if (inviteInfo.getSsrcInfo() != null) {
|
||||
inviteInfoInRedis.setSsrcInfo(inviteInfo.getSsrcInfo());
|
||||
}
|
||||
if (inviteInfo.getStreamMode() != null) {
|
||||
inviteInfoInRedis.setStreamMode(inviteInfo.getStreamMode());
|
||||
}
|
||||
if (inviteInfo.getReceiveIp() != null) {
|
||||
inviteInfoInRedis.setReceiveIp(inviteInfo.getReceiveIp());
|
||||
}
|
||||
if (inviteInfo.getReceivePort() != null) {
|
||||
inviteInfoInRedis.setReceivePort(inviteInfo.getReceivePort());
|
||||
}
|
||||
if (inviteInfo.getStatus() != null) {
|
||||
inviteInfoInRedis.setStatus(inviteInfo.getStatus());
|
||||
}
|
||||
|
||||
inviteInfoForUpdate = inviteInfoInRedis;
|
||||
|
||||
}
|
||||
String key = VideoManagerConstants.INVITE_PREFIX +
|
||||
"_" + inviteInfoForUpdate.getType() +
|
||||
"_" + inviteInfoForUpdate.getDeviceId() +
|
||||
"_" + inviteInfoForUpdate.getChannelId() +
|
||||
"_" + inviteInfoForUpdate.getStream();
|
||||
redisTemplate.opsForValue().set(key, inviteInfoForUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InviteInfo getInviteInfo(InviteSessionType type, String deviceId, String channelId, String stream) {
|
||||
String key = VideoManagerConstants.INVITE_PREFIX +
|
||||
"_" + (type != null ? type : "*") +
|
||||
"_" + (deviceId != null ? deviceId : "*") +
|
||||
"_" + (channelId != null ? channelId : "*") +
|
||||
"_" + (stream != null ? stream : "*");
|
||||
List<Object> scanResult = RedisUtil.scan(redisTemplate, key);
|
||||
if (scanResult.size() != 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (InviteInfo) redisTemplate.opsForValue().get(scanResult.get(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public InviteInfo getInviteInfoByDeviceAndChannel(InviteSessionType type, String deviceId, String channelId) {
|
||||
return getInviteInfo(type, deviceId, channelId, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InviteInfo getInviteInfoByStream(InviteSessionType type, String stream) {
|
||||
return getInviteInfo(type, null, null, stream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeInviteInfo(InviteSessionType type, String deviceId, String channelId, String stream) {
|
||||
String scanKey = VideoManagerConstants.INVITE_PREFIX +
|
||||
"_" + (type != null ? type : "*") +
|
||||
"_" + (deviceId != null ? deviceId : "*") +
|
||||
"_" + (channelId != null ? channelId : "*") +
|
||||
"_" + (stream != null ? stream : "*");
|
||||
List<Object> scanResult = RedisUtil.scan(redisTemplate, scanKey);
|
||||
if (scanResult.size() > 0) {
|
||||
for (Object keyObj : scanResult) {
|
||||
String key = (String) keyObj;
|
||||
InviteInfo inviteInfo = (InviteInfo) redisTemplate.opsForValue().get(key);
|
||||
if (inviteInfo == null) {
|
||||
continue;
|
||||
}
|
||||
redisTemplate.delete(key);
|
||||
inviteErrorCallbackMap.remove(buildKey(type, deviceId, channelId, inviteInfo.getStream()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeInviteInfoByDeviceAndChannel(InviteSessionType inviteSessionType, String deviceId, String channelId) {
|
||||
removeInviteInfo(inviteSessionType, deviceId, channelId, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeInviteInfo(InviteInfo inviteInfo) {
|
||||
removeInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId(), inviteInfo.getChannelId(), inviteInfo.getStream());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void once(InviteSessionType type, String deviceId, String channelId, String stream, InviteErrorCallback<Object> callback) {
|
||||
String key = buildKey(type, deviceId, channelId, stream);
|
||||
List<InviteErrorCallback<Object>> callbacks = inviteErrorCallbackMap.get(key);
|
||||
if (callbacks == null) {
|
||||
callbacks = new CopyOnWriteArrayList<>();
|
||||
inviteErrorCallbackMap.put(key, callbacks);
|
||||
}
|
||||
callbacks.add(callback);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void call(InviteSessionType type, String deviceId, String channelId, String stream, int code, String msg, Object data) {
|
||||
String key = buildKey(type, deviceId, channelId, stream);
|
||||
List<InviteErrorCallback<Object>> callbacks = inviteErrorCallbackMap.get(key);
|
||||
if (callbacks == null) {
|
||||
return;
|
||||
}
|
||||
for (InviteErrorCallback<Object> callback : callbacks) {
|
||||
callback.run(code, msg, data);
|
||||
}
|
||||
inviteErrorCallbackMap.remove(key);
|
||||
}
|
||||
|
||||
private String buildKey(InviteSessionType type, String deviceId, String channelId, String stream) {
|
||||
String key = type + "_" + deviceId + "_" + channelId;
|
||||
// 如果ssrc未null那么可以实现一个通道只能一次操作,ssrc不为null则可以支持一个通道多次invite
|
||||
if (stream != null) {
|
||||
key += ("_" + stream);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void clearInviteInfo(String deviceId) {
|
||||
removeInviteInfo(null, deviceId, null, null);
|
||||
}
|
||||
}
|
||||
@@ -3,13 +3,14 @@ package com.genersoft.iot.vmp.service.impl;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.genersoft.iot.vmp.common.CommonCallback;
|
||||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||
import com.genersoft.iot.vmp.conf.DynamicTask;
|
||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||
import com.genersoft.iot.vmp.gb28181.session.SsrcConfig;
|
||||
import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
|
||||
import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
||||
@@ -56,6 +57,9 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
@Autowired
|
||||
private SipConfig sipConfig;
|
||||
|
||||
@Autowired
|
||||
private SSRCFactory ssrcFactory;
|
||||
|
||||
@Value("${server.ssl.enabled:false}")
|
||||
private boolean sslEnabled;
|
||||
|
||||
@@ -96,6 +100,9 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
@Autowired
|
||||
private RedisTemplate<Object, Object> redisTemplate;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
@@ -107,10 +114,8 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
continue;
|
||||
}
|
||||
// 更新
|
||||
if (mediaServerItem.getSsrcConfig() == null) {
|
||||
SsrcConfig ssrcConfig = new SsrcConfig(mediaServerItem.getId(), null, sipConfig.getDomain());
|
||||
mediaServerItem.setSsrcConfig(ssrcConfig);
|
||||
redisTemplate.opsForValue().set(VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(), mediaServerItem);
|
||||
if (ssrcFactory.hasMediaServerSSRC(mediaServerItem.getId())) {
|
||||
ssrcFactory.initMediaServerSSRC(mediaServerItem.getId(), null);
|
||||
}
|
||||
// 查询redis是否存在此mediaServer
|
||||
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId();
|
||||
@@ -122,56 +127,44 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean ssrcCheck, boolean isPlayback) {
|
||||
return openRTPServer(mediaServerItem, streamId, null, ssrcCheck,isPlayback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String presetSsrc, boolean ssrcCheck,
|
||||
boolean isPlayback, Integer port, Boolean onlyAuto) {
|
||||
boolean isPlayback, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode) {
|
||||
if (mediaServerItem == null || mediaServerItem.getId() == null) {
|
||||
logger.info("[openRTPServer] 失败, mediaServerItem == null || mediaServerItem.getId() == null");
|
||||
return null;
|
||||
}
|
||||
// 获取mediaServer可用的ssrc
|
||||
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId();
|
||||
|
||||
SsrcConfig ssrcConfig = mediaServerItem.getSsrcConfig();
|
||||
if (ssrcConfig == null) {
|
||||
logger.info("media server [ {} ] ssrcConfig is null", mediaServerItem.getId());
|
||||
return null;
|
||||
String ssrc;
|
||||
if (presetSsrc != null) {
|
||||
ssrc = presetSsrc;
|
||||
}else {
|
||||
String ssrc;
|
||||
if (presetSsrc != null) {
|
||||
ssrc = presetSsrc;
|
||||
if (isPlayback) {
|
||||
ssrc = ssrcFactory.getPlayBackSsrc(mediaServerItem.getId());
|
||||
}else {
|
||||
if (isPlayback) {
|
||||
ssrc = ssrcConfig.getPlayBackSsrc();
|
||||
}else {
|
||||
ssrc = ssrcConfig.getPlaySsrc();
|
||||
}
|
||||
ssrc = ssrcFactory.getPlaySsrc(mediaServerItem.getId());
|
||||
}
|
||||
|
||||
if (streamId == null) {
|
||||
streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
|
||||
}
|
||||
int rtpServerPort;
|
||||
if (mediaServerItem.isRtpEnable()) {
|
||||
rtpServerPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId, ssrcCheck?Integer.parseInt(ssrc):0, port, onlyAuto);
|
||||
} else {
|
||||
rtpServerPort = mediaServerItem.getRtpProxyPort();
|
||||
}
|
||||
redisTemplate.opsForValue().set(key, mediaServerItem);
|
||||
return new SSRCInfo(rtpServerPort, ssrc, streamId);
|
||||
}
|
||||
|
||||
if (streamId == null) {
|
||||
streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
|
||||
}
|
||||
int rtpServerPort;
|
||||
if (mediaServerItem.isRtpEnable()) {
|
||||
rtpServerPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId, ssrcCheck?Integer.parseInt(ssrc):0, port, onlyAuto, reUsePort, tcpMode);
|
||||
} else {
|
||||
rtpServerPort = mediaServerItem.getRtpProxyPort();
|
||||
}
|
||||
return new SSRCInfo(rtpServerPort, ssrc, streamId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback) {
|
||||
public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback, Integer port, Boolean onlyAuto) {
|
||||
return openRTPServer(mediaServerItem, streamId, ssrc, ssrcCheck, isPlayback, null, null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void closeRTPServer(MediaServerItem mediaServerItem, String streamId) {
|
||||
if (mediaServerItem == null) {
|
||||
@@ -180,23 +173,33 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
zlmrtpServerFactory.closeRtpServer(mediaServerItem, streamId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeRTPServer(MediaServerItem mediaServerItem, String streamId, CommonCallback<Boolean> callback) {
|
||||
if (mediaServerItem == null) {
|
||||
callback.run(false);
|
||||
return;
|
||||
}
|
||||
zlmrtpServerFactory.closeRtpServer(mediaServerItem, streamId, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeRTPServer(String mediaServerId, String streamId) {
|
||||
MediaServerItem mediaServerItem = this.getOne(mediaServerId);
|
||||
closeRTPServer(mediaServerItem, streamId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean updateRtpServerSSRC(MediaServerItem mediaServerItem, String streamId, String ssrc) {
|
||||
return zlmrtpServerFactory.updateRtpServerSSRC(mediaServerItem, streamId, ssrc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void releaseSsrc(String mediaServerItemId, String ssrc) {
|
||||
MediaServerItem mediaServerItem = getOne(mediaServerItemId);
|
||||
if (mediaServerItem == null || ssrc == null) {
|
||||
return;
|
||||
}
|
||||
SsrcConfig ssrcConfig = mediaServerItem.getSsrcConfig();
|
||||
ssrcConfig.releaseSsrc(ssrc);
|
||||
mediaServerItem.setSsrcConfig(ssrcConfig);
|
||||
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId();
|
||||
redisTemplate.opsForValue().set(key, mediaServerItem);
|
||||
ssrcFactory.releaseSsrc(mediaServerItemId, ssrc);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -204,8 +207,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
*/
|
||||
@Override
|
||||
public void clearRTPServer(MediaServerItem mediaServerItem) {
|
||||
mediaServerItem.setSsrcConfig(new SsrcConfig(mediaServerItem.getId(), null, sipConfig.getDomain()));
|
||||
redisTemplate.opsForZSet().add(VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId(), mediaServerItem.getId(), 0);
|
||||
ssrcFactory.reset(mediaServerItem.getId());
|
||||
|
||||
}
|
||||
|
||||
@@ -215,16 +217,8 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
mediaServerMapper.update(mediaSerItem);
|
||||
MediaServerItem mediaServerItemInRedis = getOne(mediaSerItem.getId());
|
||||
MediaServerItem mediaServerItemInDataBase = mediaServerMapper.queryOne(mediaSerItem.getId());
|
||||
if (mediaServerItemInRedis != null && mediaServerItemInRedis.getSsrcConfig() != null) {
|
||||
mediaServerItemInDataBase.setSsrcConfig(mediaServerItemInRedis.getSsrcConfig());
|
||||
}else {
|
||||
mediaServerItemInDataBase.setSsrcConfig(
|
||||
new SsrcConfig(
|
||||
mediaServerItemInDataBase.getId(),
|
||||
null,
|
||||
sipConfig.getDomain()
|
||||
)
|
||||
);
|
||||
if (mediaServerItemInRedis == null || ssrcFactory.hasMediaServerSSRC(mediaSerItem.getId())) {
|
||||
ssrcFactory.initMediaServerSSRC(mediaServerItemInDataBase.getId(),null);
|
||||
}
|
||||
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItemInDataBase.getId();
|
||||
redisTemplate.opsForValue().set(key, mediaServerItemInDataBase);
|
||||
@@ -406,14 +400,8 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
}
|
||||
mediaServerMapper.update(serverItem);
|
||||
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + zlmServerConfig.getGeneralMediaServerId();
|
||||
if (redisTemplate.opsForValue().get(key) == null) {
|
||||
SsrcConfig ssrcConfig = new SsrcConfig(zlmServerConfig.getGeneralMediaServerId(), null, sipConfig.getDomain());
|
||||
serverItem.setSsrcConfig(ssrcConfig);
|
||||
}else {
|
||||
MediaServerItem mediaServerItemInRedis = JsonUtil.redisJsonToObject(redisTemplate, key, MediaServerItem.class);
|
||||
if (Objects.nonNull(mediaServerItemInRedis)) {
|
||||
serverItem.setSsrcConfig(mediaServerItemInRedis.getSsrcConfig());
|
||||
}
|
||||
if (ssrcFactory.hasMediaServerSSRC(serverItem.getId())) {
|
||||
ssrcFactory.initMediaServerSSRC(zlmServerConfig.getGeneralMediaServerId(), null);
|
||||
}
|
||||
redisTemplate.opsForValue().set(key, serverItem);
|
||||
resetOnlineServerItem(serverItem);
|
||||
@@ -711,8 +699,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
}
|
||||
// zlm连接重试
|
||||
logger.warn("[更新ZLM 保活信息]尝试链接zml id {}", mediaServerId);
|
||||
SsrcConfig ssrcConfig = new SsrcConfig(mediaServerItem.getId(), null, sipConfig.getDomain());
|
||||
mediaServerItem.setSsrcConfig(ssrcConfig);
|
||||
ssrcFactory.initMediaServerSSRC(mediaServerItem.getId(), null);
|
||||
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId();
|
||||
redisTemplate.opsForValue().set(key, mediaServerItem);
|
||||
clearRTPServer(mediaServerItem);
|
||||
@@ -761,4 +748,5 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
result.setGbSend(redisCatchStorage.getGbSendCount(mediaServerItem.getId()));
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package com.genersoft.iot.vmp.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.common.InviteInfo;
|
||||
import com.genersoft.iot.vmp.common.InviteSessionType;
|
||||
import com.genersoft.iot.vmp.conf.DynamicTask;
|
||||
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.SipSubscribe;
|
||||
import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
|
||||
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
||||
@@ -14,6 +16,7 @@ import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.service.IInviteStreamService;
|
||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.service.IPlatformService;
|
||||
import com.genersoft.iot.vmp.service.IPlayService;
|
||||
@@ -65,6 +68,9 @@ public class PlatformServiceImpl implements IPlatformService {
|
||||
@Autowired
|
||||
private IRedisCatchStorage redisCatchStorage;
|
||||
|
||||
@Autowired
|
||||
private SSRCFactory ssrcFactory;
|
||||
|
||||
@Autowired
|
||||
private IMediaServerService mediaServerService;
|
||||
|
||||
@@ -96,6 +102,8 @@ public class PlatformServiceImpl implements IPlatformService {
|
||||
@Autowired
|
||||
private IPlayService playService;
|
||||
|
||||
@Autowired
|
||||
private IInviteStreamService inviteStreamService;
|
||||
|
||||
|
||||
@Override
|
||||
@@ -198,6 +206,7 @@ public class PlatformServiceImpl implements IPlatformService {
|
||||
// 保存时启用就发送注册
|
||||
// 注册成功时由程序直接调用了online方法
|
||||
try {
|
||||
logger.info("[国标级联] 平台注册 {}", parentPlatform.getDeviceGBId());
|
||||
commanderForPlatform.register(parentPlatform, eventResult -> {
|
||||
logger.info("[国标级联] {},添加向上级注册失败,请确定上级平台可用时重新保存", parentPlatform.getServerGBId());
|
||||
}, null);
|
||||
@@ -349,6 +358,7 @@ public class PlatformServiceImpl implements IPlatformService {
|
||||
List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServer(platformId);
|
||||
if (sendRtpItems != null && sendRtpItems.size() > 0) {
|
||||
for (SendRtpItem sendRtpItem : sendRtpItems) {
|
||||
ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrc());
|
||||
redisCatchStorage.deleteSendRTPServer(platformId, sendRtpItem.getChannelId(), null, null);
|
||||
MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
|
||||
Map<String, Object> param = new HashMap<>(3);
|
||||
@@ -420,20 +430,22 @@ public class PlatformServiceImpl implements IPlatformService {
|
||||
logger.info("[国标级联] 语音喊话未找到可用的zlm. platform: {}", platform.getServerGBId());
|
||||
return;
|
||||
}
|
||||
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(platform.getServerGBId(), channelId);
|
||||
if (streamInfo != null) {
|
||||
InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, platform.getServerGBId(), channelId);
|
||||
|
||||
|
||||
if (inviteInfo != null && inviteInfo.getStreamInfo() != null) {
|
||||
// 如果zlm不存在这个流,则删除数据即可
|
||||
MediaServerItem mediaServerItemForStreamInfo = mediaServerService.getOne(streamInfo.getMediaServerId());
|
||||
MediaServerItem mediaServerItemForStreamInfo = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId());
|
||||
if (mediaServerItemForStreamInfo != null) {
|
||||
Boolean ready = zlmrtpServerFactory.isStreamReady(mediaServerItemForStreamInfo, streamInfo.getApp(), streamInfo.getStream());
|
||||
Boolean ready = zlmrtpServerFactory.isStreamReady(mediaServerItemForStreamInfo, inviteInfo.getStreamInfo().getApp(), inviteInfo.getStreamInfo().getStream());
|
||||
if (!ready) {
|
||||
// 错误存在于redis中的数据
|
||||
redisCatchStorage.stopPlay(streamInfo);
|
||||
inviteStreamService.removeInviteInfo(inviteInfo);
|
||||
}else {
|
||||
// 流确实尚在推流,直接回调结果
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("app", streamInfo.getApp());
|
||||
json.put("stream", streamInfo.getStream());
|
||||
json.put("app", inviteInfo.getStreamInfo().getApp());
|
||||
json.put("stream", inviteInfo.getStreamInfo().getStream());
|
||||
hookEvent.response(mediaServerItemForStreamInfo, json);
|
||||
return;
|
||||
}
|
||||
@@ -449,7 +461,11 @@ public class PlatformServiceImpl implements IPlatformService {
|
||||
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, ssrcCheck, false, null, true);
|
||||
if (ssrcInfo == null || ssrcInfo.getPort() < 0) {
|
||||
logger.info("[国标级联] 发起语音喊话 开启端口监听失败, platform: {}, channel: {}", platform.getServerGBId(), channelId);
|
||||
errorEvent.response(new SipSubscribe.EventResult(-1, "端口监听失败"));
|
||||
SipSubscribe.EventResult<Object> eventResult = new SipSubscribe.EventResult<>();
|
||||
eventResult.statusCode = -1;
|
||||
eventResult.msg = "端口监听失败";
|
||||
eventResult.type = SipSubscribe.EventResultType.failedToGetPort;
|
||||
errorEvent.response(eventResult);
|
||||
return;
|
||||
}
|
||||
logger.info("[国标级联] 语音喊话,发起Invite消息 deviceId: {}, channelId: {},收流端口: {}, 收流模式:{}, SSRC: {}, SSRC校验:{}",
|
||||
@@ -458,7 +474,8 @@ public class PlatformServiceImpl implements IPlatformService {
|
||||
String timeOutTaskKey = UUID.randomUUID().toString();
|
||||
dynamicTask.startDelay(timeOutTaskKey, () -> {
|
||||
// 执行超时任务时查询是否已经成功,成功了则不执行超时任务,防止超时任务取消失败的情况
|
||||
if (redisCatchStorage.queryPlayByDevice(platform.getServerGBId(), channelId) == null) {
|
||||
InviteInfo inviteInfoForBroadcast = inviteStreamService.getInviteInfo(InviteSessionType.BROADCAST, platform.getServerGBId(), channelId, null);
|
||||
if (inviteInfoForBroadcast == null) {
|
||||
logger.info("[国标级联] 发起语音喊话 收流超时 deviceId: {}, channelId: {},端口:{}, SSRC: {}", platform.getServerGBId(), channelId, ssrcInfo.getPort(), ssrcInfo.getSsrc());
|
||||
// 点播超时回复BYE 同时释放ssrc以及此次点播的资源
|
||||
try {
|
||||
@@ -501,7 +518,7 @@ public class PlatformServiceImpl implements IPlatformService {
|
||||
if (!mediaServerItem.isRtpEnable()) {
|
||||
logger.info("[点播消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse);
|
||||
|
||||
if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) {
|
||||
if (!ssrcFactory.checkSsrc(mediaServerItem.getId(), ssrcInResponse)) {
|
||||
// ssrc 不可用
|
||||
// 释放ssrc
|
||||
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -264,8 +264,8 @@ public class RedisGbPlayMsgListener implements MessageListener {
|
||||
return;
|
||||
}
|
||||
// 确定流是否在线
|
||||
boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, content.getApp(), content.getStream());
|
||||
if (streamReady) {
|
||||
Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, content.getApp(), content.getStream());
|
||||
if (streamReady != null && streamReady) {
|
||||
logger.info("[回复推流信息] {}/{}", content.getApp(), content.getStream());
|
||||
responseSendItem(mediaServerItem, content, toId, serial);
|
||||
}else {
|
||||
@@ -301,9 +301,6 @@ public class RedisGbPlayMsgListener implements MessageListener {
|
||||
String key = VideoManagerConstants.VM_MSG_STREAM_PUSH_REQUESTED;
|
||||
logger.info("[redis发送通知] 推流被请求 {}: {}/{}", key, messageForPushChannel.getApp(), messageForPushChannel.getStream());
|
||||
redisTemplate.convertAndSend(key, JSON.toJSON(messageForPushChannel));
|
||||
|
||||
// redisCatchStorage.sendStreamPushRequestedMsg(messageForPushChannel);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.service.redisMsg;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||
import com.genersoft.iot.vmp.conf.DynamicTask;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.service.IStreamPushService;
|
||||
import com.genersoft.iot.vmp.service.bean.PushStreamStatusChangeFromRedisDto;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
@@ -38,6 +39,9 @@ public class RedisPushStreamStatusMsgListener implements MessageListener, Applic
|
||||
@Autowired
|
||||
private DynamicTask dynamicTask;
|
||||
|
||||
@Autowired
|
||||
private UserSetting userSetting;
|
||||
|
||||
|
||||
|
||||
private ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>();
|
||||
@@ -89,13 +93,15 @@ public class RedisPushStreamStatusMsgListener implements MessageListener, Applic
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) throws Exception {
|
||||
// 启动时设置所有推流通道离线,发起查询请求
|
||||
redisCatchStorage.sendStreamPushRequestedMsgForStatus();
|
||||
dynamicTask.startDelay(VideoManagerConstants.VM_MSG_GET_ALL_ONLINE_REQUESTED, ()->{
|
||||
logger.info("[REDIS消息]未收到redis回复推流设备状态,执行推流设备离线");
|
||||
// 五秒收不到请求就设置通道离线,然后通知上级离线
|
||||
streamPushService.allStreamOffline();
|
||||
}, 5000);
|
||||
if (!userSetting.isUsePushingAsStatus()) {
|
||||
// 启动时设置所有推流通道离线,发起查询请求
|
||||
redisCatchStorage.sendStreamPushRequestedMsgForStatus();
|
||||
dynamicTask.startDelay(VideoManagerConstants.VM_MSG_GET_ALL_ONLINE_REQUESTED, ()->{
|
||||
logger.info("[REDIS消息]未收到redis回复推流设备状态,执行推流设备离线");
|
||||
// 五秒收不到请求就设置通道离线,然后通知上级离线
|
||||
streamPushService.allStreamOffline();
|
||||
}, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user