Merge branch 'wvp-28181-2.0' into main-dev
# Conflicts: # src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java # src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java # src/main/java/com/genersoft/iot/vmp/service/IPlayService.java # src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java # src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java # src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java
This commit is contained in:
@@ -87,4 +87,9 @@ public interface IDeviceChannelService {
|
||||
* 直接批量添加
|
||||
*/
|
||||
void batchAddChannel(List<DeviceChannel> deviceChannels);
|
||||
|
||||
/**
|
||||
* 修改通道的码流类型
|
||||
*/
|
||||
void updateChannelStreamIdentification(DeviceChannel channel);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.genersoft.iot.vmp.service;
|
||||
|
||||
import com.genersoft.iot.vmp.common.CommonCallback;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
|
||||
@@ -39,7 +40,7 @@ public interface IDeviceService {
|
||||
* @param device 设备信息
|
||||
* @return 布尔
|
||||
*/
|
||||
boolean removeCatalogSubscribe(Device device);
|
||||
boolean removeCatalogSubscribe(Device device, CommonCallback<Boolean> callback);
|
||||
|
||||
/**
|
||||
* 添加移动位置订阅
|
||||
@@ -53,7 +54,7 @@ public interface IDeviceService {
|
||||
* @param device 设备信息
|
||||
* @return 布尔
|
||||
*/
|
||||
boolean removeMobilePositionSubscribe(Device device);
|
||||
boolean removeMobilePositionSubscribe(Device device, CommonCallback<Boolean> callback);
|
||||
|
||||
/**
|
||||
* 移除移动位置订阅
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.conf.exception.ServiceException;
|
||||
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.gb28181.bean.DeviceChannel;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
@@ -25,7 +26,7 @@ import java.util.Map;
|
||||
*/
|
||||
public interface IPlayService {
|
||||
|
||||
void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
|
||||
void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channelId,
|
||||
ErrorCallback<Object> callback);
|
||||
SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<Object> callback);
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -267,5 +268,16 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updateChannelStreamIdentification(DeviceChannel channel) {
|
||||
assert !ObjectUtils.isEmpty(channel.getDeviceId());
|
||||
assert !ObjectUtils.isEmpty(channel.getStreamIdentification());
|
||||
if (ObjectUtils.isEmpty(channel.getStreamIdentification())) {
|
||||
logger.info("[重置通道码流类型] 设备: {}, 码流: {}", channel.getDeviceId(), channel.getStreamIdentification());
|
||||
}else {
|
||||
logger.info("[更新通道码流类型] 设备: {}, 通道:{}, 码流: {}", channel.getDeviceId(), channel.getChannelId(),
|
||||
channel.getStreamIdentification());
|
||||
}
|
||||
channelMapper.updateChannelStreamIdentification(channel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.genersoft.iot.vmp.service.impl;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
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.UserSetting;
|
||||
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager;
|
||||
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||
@@ -145,10 +145,6 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
}
|
||||
sync(device);
|
||||
}else {
|
||||
|
||||
if (deviceInDb != null) {
|
||||
device.setSwitchPrimarySubStream(deviceInDb.isSwitchPrimarySubStream());
|
||||
}
|
||||
if(!device.isOnLine()){
|
||||
device.setOnLine(true);
|
||||
device.setCreateTime(now);
|
||||
@@ -238,12 +234,8 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
}
|
||||
}
|
||||
// 移除订阅
|
||||
removeCatalogSubscribe(device);
|
||||
removeMobilePositionSubscribe(device);
|
||||
if (userSetting.getDeviceStatusNotify()) {
|
||||
// 发送redis消息
|
||||
redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), null, false);
|
||||
}
|
||||
removeCatalogSubscribe(device, null);
|
||||
removeMobilePositionSubscribe(device, null);
|
||||
|
||||
List<AudioBroadcastCatch> audioBroadcastCatches = audioBroadcastManager.get(deviceId);
|
||||
if (audioBroadcastCatches.size() > 0) {
|
||||
@@ -281,7 +273,7 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeCatalogSubscribe(Device device) {
|
||||
public boolean removeCatalogSubscribe(Device device, CommonCallback<Boolean> callback) {
|
||||
if (device == null || device.getSubscribeCycleForCatalog() < 0) {
|
||||
return false;
|
||||
}
|
||||
@@ -291,7 +283,7 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
Runnable runnable = dynamicTask.get(taskKey);
|
||||
if (runnable instanceof ISubscribeTask) {
|
||||
ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
|
||||
subscribeTask.stop();
|
||||
subscribeTask.stop(callback);
|
||||
}
|
||||
}
|
||||
dynamicTask.stop(taskKey);
|
||||
@@ -314,7 +306,7 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeMobilePositionSubscribe(Device device) {
|
||||
public boolean removeMobilePositionSubscribe(Device device, CommonCallback<Boolean> callback) {
|
||||
if (device == null || device.getSubscribeCycleForCatalog() < 0) {
|
||||
return false;
|
||||
}
|
||||
@@ -324,7 +316,7 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
Runnable runnable = dynamicTask.get(taskKey);
|
||||
if (runnable instanceof ISubscribeTask) {
|
||||
ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
|
||||
subscribeTask.stop();
|
||||
subscribeTask.stop(callback);
|
||||
}
|
||||
}
|
||||
dynamicTask.stop(taskKey);
|
||||
@@ -515,21 +507,6 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
logger.warn("更新设备时未找到设备信息");
|
||||
return;
|
||||
}
|
||||
if(deviceInStore.isSwitchPrimarySubStream() != device.isSwitchPrimarySubStream()){
|
||||
//当修改设备的主子码流开关时,需要校验是否存在流,如果存在流则直接关闭
|
||||
List<SsrcTransaction> ssrcTransactionForAll = streamSession.getSsrcTransactionForAll(device.getDeviceId(), null, null, null);
|
||||
if(ssrcTransactionForAll != null){
|
||||
for (SsrcTransaction ssrcTransaction: ssrcTransactionForAll) {
|
||||
try {
|
||||
cmder.streamByeCmd(device, ssrcTransaction.getChannelId(), ssrcTransaction.getStream(), null, null);
|
||||
} catch (InvalidArgumentException | SsrcTransactionNotFoundException | ParseException | SipException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
deviceChannelMapper.clearPlay(device.getDeviceId());
|
||||
inviteStreamService.clearInviteInfo(device.getDeviceId());
|
||||
}
|
||||
|
||||
if (!ObjectUtils.isEmpty(device.getName())) {
|
||||
deviceInStore.setName(device.getName());
|
||||
@@ -552,39 +529,54 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
if (!ObjectUtils.isEmpty(device.getStreamMode())) {
|
||||
deviceInStore.setStreamMode(device.getStreamMode());
|
||||
}
|
||||
|
||||
|
||||
// 目录订阅相关的信息
|
||||
if (deviceInStore.getSubscribeCycleForCatalog() != device.getSubscribeCycleForCatalog()) {
|
||||
if (device.getSubscribeCycleForCatalog() > 0) {
|
||||
// 若已开启订阅,但订阅周期不同,则先取消
|
||||
if (deviceInStore.getSubscribeCycleForCatalog() != 0) {
|
||||
removeCatalogSubscribe(deviceInStore);
|
||||
removeCatalogSubscribe(deviceInStore, result->{
|
||||
// 开启订阅
|
||||
deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog());
|
||||
addCatalogSubscribe(deviceInStore);
|
||||
// 因为是异步执行,需要在这里更新下数据
|
||||
deviceMapper.updateCustom(deviceInStore);
|
||||
redisCatchStorage.updateDevice(deviceInStore);
|
||||
});
|
||||
}else {
|
||||
// 开启订阅
|
||||
deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog());
|
||||
addCatalogSubscribe(deviceInStore);
|
||||
}
|
||||
// 开启订阅
|
||||
deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog());
|
||||
addCatalogSubscribe(deviceInStore);
|
||||
|
||||
}else if (device.getSubscribeCycleForCatalog() == 0) {
|
||||
// 取消订阅
|
||||
deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog());
|
||||
removeCatalogSubscribe(deviceInStore);
|
||||
deviceInStore.setSubscribeCycleForCatalog(0);
|
||||
removeCatalogSubscribe(deviceInStore, null);
|
||||
}
|
||||
}
|
||||
|
||||
// 移动位置订阅相关的信息
|
||||
if (device.getSubscribeCycleForMobilePosition() > 0) {
|
||||
if (deviceInStore.getSubscribeCycleForMobilePosition() == 0 || deviceInStore.getSubscribeCycleForMobilePosition() != device.getSubscribeCycleForMobilePosition()) {
|
||||
deviceInStore.setMobilePositionSubmissionInterval(device.getMobilePositionSubmissionInterval());
|
||||
deviceInStore.setSubscribeCycleForMobilePosition(device.getSubscribeCycleForMobilePosition());
|
||||
// 开启订阅
|
||||
addMobilePositionSubscribe(deviceInStore);
|
||||
}
|
||||
}else if (device.getSubscribeCycleForMobilePosition() == 0) {
|
||||
if (deviceInStore.getSubscribeCycleForMobilePosition() != 0) {
|
||||
deviceInStore.setMobilePositionSubmissionInterval(device.getMobilePositionSubmissionInterval());
|
||||
deviceInStore.setSubscribeCycleForMobilePosition(device.getSubscribeCycleForMobilePosition());
|
||||
if (deviceInStore.getSubscribeCycleForMobilePosition() != device.getSubscribeCycleForMobilePosition()) {
|
||||
if (device.getSubscribeCycleForMobilePosition() > 0) {
|
||||
// 若已开启订阅,但订阅周期不同,则先取消
|
||||
if (deviceInStore.getSubscribeCycleForMobilePosition() != 0) {
|
||||
removeMobilePositionSubscribe(deviceInStore, result->{
|
||||
// 开启订阅
|
||||
deviceInStore.setSubscribeCycleForMobilePosition(device.getSubscribeCycleForMobilePosition());
|
||||
addMobilePositionSubscribe(deviceInStore);
|
||||
// 因为是异步执行,需要在这里更新下数据
|
||||
deviceMapper.updateCustom(deviceInStore);
|
||||
redisCatchStorage.updateDevice(deviceInStore);
|
||||
});
|
||||
}else {
|
||||
// 开启订阅
|
||||
deviceInStore.setSubscribeCycleForMobilePosition(device.getSubscribeCycleForMobilePosition());
|
||||
addMobilePositionSubscribe(deviceInStore);
|
||||
}
|
||||
|
||||
}else if (device.getSubscribeCycleForMobilePosition() == 0) {
|
||||
// 取消订阅
|
||||
removeMobilePositionSubscribe(deviceInStore);
|
||||
deviceInStore.setSubscribeCycleForCatalog(0);
|
||||
removeCatalogSubscribe(deviceInStore, null);
|
||||
}
|
||||
}
|
||||
if (deviceInStore.getGeoCoordSys() != null) {
|
||||
@@ -603,10 +595,9 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
deviceInStore.setSsrcCheck(device.isSsrcCheck());
|
||||
//作为消息通道
|
||||
deviceInStore.setAsMessageChannel(device.isAsMessageChannel());
|
||||
|
||||
// 更新redis
|
||||
|
||||
deviceMapper.updateCustom(deviceInStore);
|
||||
redisCatchStorage.removeDevice(deviceInStore.getDeviceId());
|
||||
redisCatchStorage.updateDevice(deviceInStore);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,6 +20,8 @@ import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
|
||||
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory;
|
||||
@@ -29,6 +31,10 @@ import com.genersoft.iot.vmp.media.zlm.*;
|
||||
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.media.zlm.dto.HookSubscribeFactory;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForRecordMp4;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
|
||||
@@ -39,9 +45,12 @@ import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
|
||||
import com.genersoft.iot.vmp.service.bean.RequestPushStreamMsg;
|
||||
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
||||
import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener;
|
||||
import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
|
||||
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
import com.genersoft.iot.vmp.storager.dao.CloudRecordServiceMapper;
|
||||
import com.genersoft.iot.vmp.utils.CloudRecordUtils;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult;
|
||||
@@ -80,7 +89,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||
private IVideoManagerStorage storager;
|
||||
|
||||
@Autowired
|
||||
private SIPCommander cmder;
|
||||
private ISIPCommander cmder;
|
||||
|
||||
@Autowired
|
||||
private AudioBroadcastManager audioBroadcastManager;
|
||||
@@ -121,6 +130,9 @@ public class PlayServiceImpl implements IPlayService {
|
||||
@Autowired
|
||||
private UserSetting userSetting;
|
||||
|
||||
@Autowired
|
||||
private IDeviceChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private SipConfig sipConfig;
|
||||
|
||||
@@ -163,6 +175,11 @@ public class PlayServiceImpl implements IPlayService {
|
||||
logger.warn("[点播] 单端口收流时不支持TCP主动方式收流 deviceId: {},channelId:{}", deviceId, channelId);
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "单端口收流时不支持TCP主动方式收流");
|
||||
}
|
||||
DeviceChannel channel = channelService.getOne(deviceId, channelId);
|
||||
if (channel == null) {
|
||||
logger.warn("[点播] 未找到通道 deviceId: {},channelId:{}", deviceId, channelId);
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到通道");
|
||||
}
|
||||
InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId);
|
||||
if (inviteInfo != null ) {
|
||||
if (inviteInfo.getStreamInfo() == null) {
|
||||
@@ -211,7 +228,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||
null);
|
||||
return null;
|
||||
}
|
||||
play(mediaServerItem, ssrcInfo, device, channelId, callback);
|
||||
play(mediaServerItem, ssrcInfo, device, channel, callback);
|
||||
return ssrcInfo;
|
||||
}
|
||||
|
||||
@@ -358,7 +375,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||
|
||||
|
||||
@Override
|
||||
public void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
|
||||
public void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel,
|
||||
ErrorCallback<Object> callback) {
|
||||
|
||||
if (mediaServerItem == null || ssrcInfo == null) {
|
||||
@@ -367,111 +384,109 @@ public class PlayServiceImpl implements IPlayService {
|
||||
null);
|
||||
return;
|
||||
}
|
||||
logger.info("[点播开始] deviceId: {}, channelId: {},码流类型:{}, 收流端口: {}, STREAM:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}",
|
||||
device.getDeviceId(), channelId, device.isSwitchPrimarySubStream() ? "辅码流" : "主码流", ssrcInfo.getPort(), ssrcInfo.getStream(),
|
||||
logger.info("[点播开始] deviceId: {}, channelId: {},码流类型:{}, 收流端口: {}, 码流:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}",
|
||||
device.getDeviceId(), channel.getChannelId(), channel.getStreamIdentification(), ssrcInfo.getPort(), ssrcInfo.getStream(),
|
||||
device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck());
|
||||
//端口获取失败的ssrcInfo 没有必要发送点播指令
|
||||
if (ssrcInfo.getPort() <= 0) {
|
||||
logger.info("[点播端口分配异常],deviceId={},channelId={},ssrcInfo={}", device.getDeviceId(), channelId, ssrcInfo);
|
||||
logger.info("[点播端口分配异常],deviceId={},channelId={},ssrcInfo={}", device.getDeviceId(), channel.getChannelId(), ssrcInfo);
|
||||
// 释放ssrc
|
||||
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
|
||||
streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
|
||||
streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
|
||||
|
||||
callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "点播端口分配异常", null);
|
||||
inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null,
|
||||
inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null,
|
||||
InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "点播端口分配异常", null);
|
||||
return;
|
||||
}
|
||||
|
||||
// 初始化redis中的invite消息状态
|
||||
InviteInfo inviteInfo = InviteInfo.getInviteInfo(device.getDeviceId(), channelId, ssrcInfo.getStream(), ssrcInfo,
|
||||
InviteInfo inviteInfo = InviteInfo.getInviteInfo(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream(), ssrcInfo,
|
||||
mediaServerItem.getSdpIp(), ssrcInfo.getPort(), device.getStreamMode(), InviteSessionType.PLAY,
|
||||
InviteSessionStatus.ready);
|
||||
inviteInfo.setSubStream(device.isSwitchPrimarySubStream());
|
||||
inviteStreamService.updateInviteInfo(inviteInfo);
|
||||
// 超时处理
|
||||
String timeOutTaskKey = UUID.randomUUID().toString();
|
||||
dynamicTask.startDelay(timeOutTaskKey, () -> {
|
||||
// 执行超时任务时查询是否已经成功,成功了则不执行超时任务,防止超时任务取消失败的情况
|
||||
InviteInfo inviteInfoForTimeOut = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId);
|
||||
InviteInfo inviteInfoForTimeOut = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId());
|
||||
if (inviteInfoForTimeOut == null || inviteInfoForTimeOut.getStreamInfo() == null) {
|
||||
logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},码流类型:{},端口:{}, SSRC: {}",
|
||||
device.getDeviceId(), channelId, device.isSwitchPrimarySubStream() ? "辅码流" : "主码流",
|
||||
logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},码流:{},端口:{}, SSRC: {}",
|
||||
device.getDeviceId(), channel.getChannelId(), channel.getStreamIdentification(),
|
||||
ssrcInfo.getPort(), ssrcInfo.getSsrc());
|
||||
|
||||
callback.run(InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode(), InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getMsg(), null);
|
||||
inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null,
|
||||
inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null,
|
||||
InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode(), InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getMsg(), null);
|
||||
inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId);
|
||||
inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId());
|
||||
|
||||
try {
|
||||
cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null);
|
||||
} catch (InvalidArgumentException | ParseException | SipException |
|
||||
SsrcTransactionNotFoundException e) {
|
||||
cmder.streamByeCmd(device, channel.getChannelId(), ssrcInfo.getStream(), null);
|
||||
} catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) {
|
||||
logger.error("[点播超时], 发送BYE失败 {}", e.getMessage());
|
||||
} finally {
|
||||
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
|
||||
mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
|
||||
streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
|
||||
streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
|
||||
mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
|
||||
// 取消订阅消息监听
|
||||
HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId());
|
||||
subscribe.removeSubscribe(hookSubscribe);
|
||||
}
|
||||
}else {
|
||||
logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},码流类型:{},端口:{}, SSRC: {}",
|
||||
device.getDeviceId(), channelId, device.isSwitchPrimarySubStream() ? "辅码流" : "主码流",
|
||||
logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},码流:{},端口:{}, SSRC: {}",
|
||||
device.getDeviceId(), channel.getChannelId(), channel.getStreamIdentification(),
|
||||
ssrcInfo.getPort(), ssrcInfo.getSsrc());
|
||||
|
||||
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
|
||||
|
||||
mediaServerService.closeRTPServer(mediaServerItem.getId(), ssrcInfo.getStream());
|
||||
streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
|
||||
streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
|
||||
}
|
||||
}, userSetting.getPlayTimeout());
|
||||
|
||||
try {
|
||||
cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (mediaServerItemInuse, hookParam ) -> {
|
||||
cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channel, (mediaServerItemInuse, hookParam ) -> {
|
||||
logger.info("收到订阅消息: " + hookParam);
|
||||
dynamicTask.stop(timeOutTaskKey);
|
||||
// hook响应
|
||||
StreamInfo streamInfo = onPublishHandlerForPlay(mediaServerItemInuse, hookParam, device.getDeviceId(), channelId);
|
||||
StreamInfo streamInfo = onPublishHandlerForPlay(mediaServerItemInuse, hookParam, device.getDeviceId(), channel.getChannelId());
|
||||
if (streamInfo == null){
|
||||
callback.run(InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(),
|
||||
InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null);
|
||||
inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null,
|
||||
inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null,
|
||||
InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(),
|
||||
InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null);
|
||||
return;
|
||||
}
|
||||
callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo);
|
||||
inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null,
|
||||
inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null,
|
||||
InviteErrorCode.SUCCESS.getCode(),
|
||||
InviteErrorCode.SUCCESS.getMsg(),
|
||||
streamInfo);
|
||||
logger.info("[点播成功] deviceId: {}, channelId:{}, 码流类型:{}", device.getDeviceId(), channelId,
|
||||
device.isSwitchPrimarySubStream() ? "辅码流" : "主码流");
|
||||
snapOnPlay(mediaServerItemInuse, device.getDeviceId(), channelId, ssrcInfo.getStream());
|
||||
logger.info("[点播成功] deviceId: {}, channelId:{}, 码流类型:{}", device.getDeviceId(), channel.getChannelId(),
|
||||
channel.getStreamIdentification());
|
||||
snapOnPlay(mediaServerItemInuse, device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
|
||||
}, (eventResult) -> {
|
||||
// 处理收到200ok后的TCP主动连接以及SSRC不一致的问题
|
||||
InviteOKHandler(eventResult, ssrcInfo, mediaServerItem, device, channelId,
|
||||
InviteOKHandler(eventResult, ssrcInfo, mediaServerItem, device, channel.getChannelId(),
|
||||
timeOutTaskKey, callback, inviteInfo, InviteSessionType.PLAY);
|
||||
}, (event) -> {
|
||||
logger.info("[点播失败] deviceId: {}, channelId:{}, {}: {}", device.getDeviceId(), channelId, event.statusCode, event.msg);
|
||||
logger.info("[点播失败] deviceId: {}, channelId:{}, {}: {}", device.getDeviceId(), channel.getChannelId(), event.statusCode, event.msg);
|
||||
dynamicTask.stop(timeOutTaskKey);
|
||||
mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
|
||||
// 释放ssrc
|
||||
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
|
||||
|
||||
streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
|
||||
streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
|
||||
|
||||
callback.run(InviteErrorCode.ERROR_FOR_SIGNALLING_ERROR.getCode(),
|
||||
String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg), null);
|
||||
inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null,
|
||||
inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null,
|
||||
InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(),
|
||||
String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg), null);
|
||||
|
||||
inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId);
|
||||
inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId());
|
||||
});
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
|
||||
@@ -481,15 +496,15 @@ public class PlayServiceImpl implements IPlayService {
|
||||
// 释放ssrc
|
||||
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
|
||||
|
||||
streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
|
||||
streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
|
||||
|
||||
callback.run(InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getCode(),
|
||||
InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getMsg(), null);
|
||||
inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null,
|
||||
inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null,
|
||||
InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getCode(),
|
||||
InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getMsg(), null);
|
||||
|
||||
inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId);
|
||||
inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -626,7 +641,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||
|
||||
@Override
|
||||
public void playBack(String deviceId, String channelId, String startTime,
|
||||
String endTime, ErrorCallback<Object> callback) {
|
||||
String endTime, ErrorCallback<Object> callback) {
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
if (device == null) {
|
||||
logger.warn("[录像回放] 未找到设备 deviceId: {},channelId:{}", deviceId, channelId);
|
||||
@@ -651,8 +666,8 @@ public class PlayServiceImpl implements IPlayService {
|
||||
|
||||
@Override
|
||||
public void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,
|
||||
String deviceId, String channelId, String startTime,
|
||||
String endTime, ErrorCallback<Object> callback) {
|
||||
String deviceId, String channelId, String startTime,
|
||||
String endTime, ErrorCallback<Object> callback) {
|
||||
if (mediaServerItem == null || ssrcInfo == null) {
|
||||
callback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(),
|
||||
InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getMsg(),
|
||||
@@ -1548,16 +1563,16 @@ public class PlayServiceImpl implements IPlayService {
|
||||
|
||||
MediaServerItem newMediaServerItem = getNewMediaServerItem(device);
|
||||
play(newMediaServerItem, deviceId, channelId, null, (code, msg, data)->{
|
||||
if (code == InviteErrorCode.SUCCESS.getCode()) {
|
||||
InviteInfo inviteInfoForPlay = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId);
|
||||
if (inviteInfoForPlay != null && inviteInfoForPlay.getStreamInfo() != null) {
|
||||
getSnap(deviceId, channelId, fileName, errorCallback);
|
||||
}else {
|
||||
errorCallback.run(InviteErrorCode.FAIL.getCode(), InviteErrorCode.FAIL.getMsg(), null);
|
||||
}
|
||||
}else {
|
||||
errorCallback.run(InviteErrorCode.FAIL.getCode(), InviteErrorCode.FAIL.getMsg(), null);
|
||||
}
|
||||
if (code == InviteErrorCode.SUCCESS.getCode()) {
|
||||
InviteInfo inviteInfoForPlay = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId);
|
||||
if (inviteInfoForPlay != null && inviteInfoForPlay.getStreamInfo() != null) {
|
||||
getSnap(deviceId, channelId, fileName, errorCallback);
|
||||
}else {
|
||||
errorCallback.run(InviteErrorCode.FAIL.getCode(), InviteErrorCode.FAIL.getMsg(), null);
|
||||
}
|
||||
}else {
|
||||
errorCallback.run(InviteErrorCode.FAIL.getCode(), InviteErrorCode.FAIL.getMsg(), null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user