重构INVITE消息处理中的上级点播请求

This commit is contained in:
648540858
2024-08-14 17:19:19 +08:00
parent d5621f9489
commit cce1d1de40
28 changed files with 489 additions and 406 deletions

View File

@@ -1,20 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.media.bean.MediaServer;
import lombok.Data;
@Data
public class CommonChannelPlayInfo {
private StreamInfo streamInfo;
private MediaServer mediaServer;
public static CommonChannelPlayInfo build(MediaServer mediaServer, StreamInfo data) {
CommonChannelPlayInfo commonChannelPlayInfo = new CommonChannelPlayInfo();
commonChannelPlayInfo.setMediaServer(mediaServer);
commonChannelPlayInfo.setStreamInfo(data);
return commonChannelPlayInfo;
}
}

View File

@@ -256,7 +256,7 @@ public class PlatformController {
boolean deleteResult = storager.deleteParentPlatform(parentPlatform);
// storager.delCatalogByPlatformId(parentPlatform.getServerGBId());
storager.delRelationByPlatformId(parentPlatform.getServerGBId());
// storager.delRelationByPlatformId(parentPlatform.getServerGBId());
// 停止发送位置订阅定时任务
String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() + "_MobilePosition_" + parentPlatform.getServerGBId();
dynamicTask.stop(key);
@@ -396,11 +396,11 @@ public class PlatformController {
if (log.isDebugEnabled()) {
log.debug("删除关联,{}", JSON.toJSONString(platformCatalog));
}
int delResult = storager.delRelation(platformCatalog);
if (delResult <= 0) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "写入数据库失败");
}
// int delResult = storager.delRelation(platformCatalog);
//
// if (delResult <= 0) {
// throw new ControllerException(ErrorCode.ERROR100.getCode(), "写入数据库失败");
// }
}

View File

@@ -0,0 +1,12 @@
package com.genersoft.iot.vmp.gb28181.service;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
import com.genersoft.iot.vmp.gb28181.bean.InviteInfo;
import com.genersoft.iot.vmp.gb28181.bean.Platform;
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
public interface IGbChannelPlayService {
void start(CommonGBChannel channel, InviteInfo inviteInfo, Platform platform, ErrorCallback<StreamInfo> callback);
}

View File

@@ -1,7 +1,6 @@
package com.genersoft.iot.vmp.gb28181.service;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
import com.github.pagehelper.PageInfo;
import java.util.Collection;
@@ -79,5 +78,4 @@ public interface IGbChannelService {
CommonGBChannel queryOneWithPlatform(Integer platformId, String channelDeviceId);
void start(CommonGBChannel channel, InviteInfo inviteInfo, ErrorCallback<CommonChannelPlayInfo> callback);
}

View File

@@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.service;
import com.genersoft.iot.vmp.common.InviteInfo;
import com.genersoft.iot.vmp.common.InviteSessionType;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
/**
@@ -58,12 +59,12 @@ public interface IInviteStreamService {
/**
* 添加一个invite回调
*/
void once(InviteSessionType type, String deviceId, String channelId, String stream, ErrorCallback<Object> callback);
void once(InviteSessionType type, String deviceId, String channelId, String stream, ErrorCallback<StreamInfo> callback);
/**
* 调用一个invite回调
*/
void call(InviteSessionType type, String deviceId, String channelId, String stream, int code, String msg, Object data);
void call(InviteSessionType type, String deviceId, String channelId, String stream, int code, String msg, StreamInfo data);
/**
* 清空一个设备的所有invite信息

View File

@@ -2,10 +2,7 @@ package com.genersoft.iot.vmp.gb28181.service;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.exception.ServiceException;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.Platform;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.media.bean.MediaInfo;
import com.genersoft.iot.vmp.media.bean.MediaServer;
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
@@ -25,19 +22,19 @@ import java.text.ParseException;
public interface IPlayService {
void play(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channelId,
ErrorCallback<Object> callback);
ErrorCallback<StreamInfo> callback);
SSRCInfo play(MediaServer mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<StreamInfo> callback);
StreamInfo onPublishHandlerForPlay(MediaServer mediaServerItem, MediaInfo mediaInfo, String deviceId, String channelId);
MediaServer getNewMediaServerItem(Device device);
void playBack(String deviceId, String channelId, String startTime, String endTime, ErrorCallback<Object> callback);
void playBack(MediaServer mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, ErrorCallback<Object> callback);
void playBack(String deviceId, String channelId, String startTime, String endTime, ErrorCallback<StreamInfo> callback);
void playBack(MediaServer mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, ErrorCallback<StreamInfo> callback);
void zlmServerOffline(String mediaServerId);
void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<Object> callback);
void download(MediaServer mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<Object> callback);
void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<StreamInfo> callback);
void download(MediaServer mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<StreamInfo> callback);
StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream);
@@ -66,4 +63,10 @@ public interface IPlayService {
void getSnap(String deviceId, String channelId, String fileName, ErrorCallback errorCallback);
void stopPlay(Device device, String channelId);
void play(CommonGBChannel channel, ErrorCallback<StreamInfo> callback);
void playBack(CommonGBChannel channel, Long startTime, Long stopTime, ErrorCallback<StreamInfo> callback);
void download(CommonGBChannel channel, Long startTime, Long stopTime, Integer downloadSpeed, ErrorCallback<StreamInfo> callback);
}

View File

@@ -0,0 +1,159 @@
package com.genersoft.iot.vmp.gb28181.service.impl;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
import com.genersoft.iot.vmp.gb28181.bean.InviteInfo;
import com.genersoft.iot.vmp.gb28181.bean.Platform;
import com.genersoft.iot.vmp.gb28181.bean.PlayException;
import com.genersoft.iot.vmp.gb28181.service.IGbChannelPlayService;
import com.genersoft.iot.vmp.gb28181.service.IPlayService;
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
import com.genersoft.iot.vmp.streamProxy.service.IStreamProxyPlayService;
import com.genersoft.iot.vmp.streamPush.service.IStreamPushPlayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.sip.message.Response;
@Slf4j
@Service
public class GbChannelPlayServiceImpl implements IGbChannelPlayService {
@Autowired
private IPlayService deviceChannelPlayService;
@Autowired
private IStreamProxyPlayService streamProxyPlayService;
@Autowired
private IStreamPushPlayService streamPushPlayService;
@Override
public void start(CommonGBChannel channel, InviteInfo inviteInfo, Platform platform, ErrorCallback<StreamInfo> callback) {
if (channel == null || inviteInfo == null || callback == null) {
log.warn("[通用通道点播] 参数异常, channel: {}, inviteInfo: {}, callback: {}", channel != null, inviteInfo != null, callback != null);
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
}
log.info("[点播通用通道] 类型:{} 通道: {}({})", inviteInfo.getSessionName(), channel.getGbName(), channel.getGbDeviceId());
if ("Play".equalsIgnoreCase(inviteInfo.getSessionName())) {
if (channel.getGbDeviceDbId() > 0) {
// 国标通道
playGbDeviceChannel(channel, callback);
} else if (channel.getStreamProxyId() > 0) {
// 拉流代理
playProxy(channel, callback);
} else if (channel.getStreamPushId() > 0) {
// 推流
playPush(channel, platform.getServerGBId(), platform.getName(), callback);
} else {
// 通道数据异常
log.error("[点播通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
}
}else if ("Playback".equals(inviteInfo.getSessionName())) {
if (channel.getGbDeviceDbId() > 0) {
// 国标通道
playbackGbDeviceChannel(channel, inviteInfo.getStartTime(), inviteInfo.getStopTime(), callback);
} else if (channel.getStreamProxyId() > 0) {
// 拉流代理
log.warn("[回放通用通道] 不支持回放拉流代理的录像: {}({})", channel.getGbName(), channel.getGbDeviceId());
throw new PlayException(Response.FORBIDDEN, "forbidden");
} else if (channel.getStreamPushId() > 0) {
// 推流
log.warn("[回放通用通道] 不支持回放推流的录像: {}({})", channel.getGbName(), channel.getGbDeviceId());
throw new PlayException(Response.FORBIDDEN, "forbidden");
} else {
// 通道数据异常
log.error("[回放通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
}
}else if ("Download".equals(inviteInfo.getSessionName())) {
if (channel.getGbDeviceDbId() > 0) {
int downloadSpeed = 4;
try {
if (inviteInfo.getDownloadSpeed() != null){
downloadSpeed = Integer.parseInt(inviteInfo.getDownloadSpeed());
}
}catch (Exception ignored) {}
// 国标通道
downloadGbDeviceChannel(channel, inviteInfo.getStartTime(), inviteInfo.getStopTime(), downloadSpeed, callback);
} else if (channel.getStreamProxyId() > 0) {
// 拉流代理
log.warn("[下载通用通道录像] 不支持下载拉流代理的录像: {}({})", channel.getGbName(), channel.getGbDeviceId());
throw new PlayException(Response.FORBIDDEN, "forbidden");
} else if (channel.getStreamPushId() > 0) {
// 推流
log.warn("[下载通用通道录像] 不支持下载推流的录像: {}({})", channel.getGbName(), channel.getGbDeviceId());
throw new PlayException(Response.FORBIDDEN, "forbidden");
} else {
// 通道数据异常
log.error("[回放通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
}
}else {
// 不支持的点播方式
log.error("[点播通用通道] 不支持的点播方式:{} {}({})", inviteInfo.getSessionName(), channel.getGbName(), channel.getGbDeviceId());
throw new PlayException(Response.BAD_REQUEST, "bad request");
}
}
private void playGbDeviceChannel(CommonGBChannel channel, ErrorCallback<StreamInfo> callback){
// 国标通道
try {
deviceChannelPlayService.play(channel, callback);
} catch (PlayException e) {
callback.run(e.getCode(), e.getMsg(), null);
} catch (Exception e) {
callback.run(Response.BUSY_HERE, "busy here", null);
}
}
private void playProxy(CommonGBChannel channel, ErrorCallback<StreamInfo> callback){
// 拉流代理通道
try {
StreamInfo streamInfo = streamProxyPlayService.start(channel.getStreamProxyId());
if (streamInfo == null) {
callback.run(Response.BUSY_HERE, "busy here", null);
}else {
callback.run(Response.OK, "success", streamInfo);
}
}catch (Exception e) {
callback.run(Response.BUSY_HERE, "busy here", null);
}
}
private void playPush(CommonGBChannel channel, String platformDeviceId, String platformName, ErrorCallback<StreamInfo> callback){
// 推流
try {
streamPushPlayService.start(channel.getStreamPushId(), callback, platformDeviceId, platformName);
}catch (PlayException e) {
callback.run(e.getCode(), e.getMsg(), null);
}catch (Exception e) {
callback.run(Response.BUSY_HERE, "busy here", null);
}
}
private void playbackGbDeviceChannel(CommonGBChannel channel, Long startTime, Long stopTime, ErrorCallback<StreamInfo> callback){
try {
deviceChannelPlayService.playBack(channel, startTime, stopTime, callback);
} catch (PlayException e) {
callback.run(e.getCode(), e.getMsg(), null);
} catch (Exception e) {
callback.run(Response.BUSY_HERE, "busy here", null);
}
}
private void downloadGbDeviceChannel(CommonGBChannel channel, Long startTime, Long stopTime, Integer downloadSpeed,
ErrorCallback<StreamInfo> callback){
try {
deviceChannelPlayService.download(channel, startTime, stopTime, downloadSpeed, callback);
} catch (PlayException e) {
callback.run(e.getCode(), e.getMsg(), null);
} catch (Exception e) {
callback.run(Response.BUSY_HERE, "busy here", null);
}
}
}

View File

@@ -1,6 +1,5 @@
package com.genersoft.iot.vmp.gb28181.service.impl;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.dao.CommonGBChannelMapper;
@@ -8,11 +7,7 @@ import com.genersoft.iot.vmp.gb28181.dao.GroupMapper;
import com.genersoft.iot.vmp.gb28181.dao.RegionMapper;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
import com.genersoft.iot.vmp.gb28181.service.IGbChannelService;
import com.genersoft.iot.vmp.gb28181.service.IPlayService;
import com.genersoft.iot.vmp.media.bean.MediaServer;
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.github.pagehelper.PageHelper;
@@ -24,7 +19,6 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import javax.sip.message.Response;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -40,21 +34,12 @@ public class GbChannelServiceImpl implements IGbChannelService {
@Autowired
private CommonGBChannelMapper commonGBChannelMapper;
@Autowired
private IDeviceService deviceService;
@Autowired
private IPlayService playService;
@Autowired
private RegionMapper regionMapper;
@Autowired
private GroupMapper groupMapper;
@Autowired
private UserSetting userSetting;
@Override
public CommonGBChannel queryByDeviceId(String gbDeviceId) {
return commonGBChannelMapper.queryByDeviceId(gbDeviceId);
@@ -652,48 +637,4 @@ public class GbChannelServiceImpl implements IGbChannelService {
public CommonGBChannel queryOneWithPlatform(Integer platformId, String channelDeviceId) {
return commonGBChannelMapper.queryOneWithPlatform(platformId, channelDeviceId);
}
@Override
public void start(CommonGBChannel channel, InviteInfo inviteInfo, ErrorCallback<CommonChannelPlayInfo> callback) {
if (channel == null || inviteInfo == null || callback == null) {
log.warn("[通用通道点播] 参数异常, channel: {}, inviteInfo: {}, callback: {}", channel != null, inviteInfo != null, callback != null);
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
}
log.info("[点播通用通道] 类型:{} 通道: {}({})", inviteInfo.getSessionName(), channel.getGbName(), channel.getGbDeviceId());
if ("Play".equalsIgnoreCase(inviteInfo.getSessionName())) {
if (channel.getGbDeviceDbId() > 0) {
// 国标通道
Device device = deviceService.getDevice(channel.getGbDeviceDbId());
if (device == null) {
log.warn("[点播] 未找到通道{}的设备信息", channel);
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
}
MediaServer mediaServer = playService.getNewMediaServerItem(device);
if (mediaServer == null) {
log.warn("[点播] 未找到可用媒体节点");
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
}
playService.play(mediaServer, device.getDeviceId(), channel.getGbDeviceId(), null, (code, msg, data) -> {
if (callback != null) {
callback.run(code, msg, CommonChannelPlayInfo.build(mediaServer, data));
}
});
} else if (channel.getStreamProxyId() > 0) {
// 拉流代理
} else if (channel.getStreamPushId() > 0) {
// 推流
} else {
// 通道数据异常
log.error("[点播通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
}
}else if ("Playback".equals(inviteInfo.getSessionName())) {
}else if ("Download".equals(inviteInfo.getSessionName())) {
}else {
}
}
}

View File

@@ -2,10 +2,7 @@ package com.genersoft.iot.vmp.gb28181.service.impl;
import com.alibaba.fastjson2.JSON;
import com.baomidou.dynamic.datasource.annotation.DS;
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.common.*;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.dao.DeviceChannelMapper;
@@ -33,7 +30,7 @@ import java.util.concurrent.TimeUnit;
@DS("master")
public class InviteStreamServiceImpl implements IInviteStreamService {
private final Map<String, List<ErrorCallback<Object>>> inviteErrorCallbackMap = new ConcurrentHashMap<>();
private final Map<String, List<ErrorCallback<StreamInfo>>> inviteErrorCallbackMap = new ConcurrentHashMap<>();
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@@ -233,9 +230,9 @@ public class InviteStreamServiceImpl implements IInviteStreamService {
}
@Override
public void once(InviteSessionType type, String deviceId, String channelId, String stream, ErrorCallback<Object> callback) {
public void once(InviteSessionType type, String deviceId, String channelId, String stream, ErrorCallback<StreamInfo> callback) {
String key = buildKey(type, deviceId, channelId, stream);
List<ErrorCallback<Object>> callbacks = inviteErrorCallbackMap.get(key);
List<ErrorCallback<StreamInfo>> callbacks = inviteErrorCallbackMap.get(key);
if (callbacks == null) {
callbacks = new CopyOnWriteArrayList<>();
inviteErrorCallbackMap.put(key, callbacks);
@@ -270,7 +267,10 @@ public class InviteStreamServiceImpl implements IInviteStreamService {
for (Object keyObj : scanResult) {
String keyStr = (String) keyObj;
InviteInfo inviteInfo = (InviteInfo) redisTemplate.opsForValue().get(keyStr);
if (inviteInfo != null && inviteInfo.getStreamInfo() != null && inviteInfo.getStreamInfo().getMediaServerId().equals(mediaServerId)) {
if (inviteInfo != null
&& inviteInfo.getStreamInfo() != null
&& inviteInfo.getStreamInfo().getMediaServer() != null
&& inviteInfo.getStreamInfo().getMediaServer().getId().equals(mediaServerId)) {
if (inviteInfo.getType().equals(InviteSessionType.DOWNLOAD) && inviteInfo.getStreamInfo().getProgress() == 1) {
continue;
}
@@ -282,13 +282,13 @@ public class InviteStreamServiceImpl implements IInviteStreamService {
}
@Override
public void call(InviteSessionType type, String deviceId, String channelId, String stream, int code, String msg, Object data) {
public void call(InviteSessionType type, String deviceId, String channelId, String stream, int code, String msg, StreamInfo data) {
String key = buildSubStreamKey(type, deviceId, channelId, stream);
List<ErrorCallback<Object>> callbacks = inviteErrorCallbackMap.get(key);
List<ErrorCallback<StreamInfo>> callbacks = inviteErrorCallbackMap.get(key);
if (callbacks == null) {
return;
}
for (ErrorCallback<Object> callback : callbacks) {
for (ErrorCallback<StreamInfo> callback : callbacks) {
callback.run(code, msg, data);
}
inviteErrorCallbackMap.remove(key);

View File

@@ -120,29 +120,29 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService {
private List<CommonGBChannel> getDeviceChannelListByChannelReduceList(List<ChannelReduce> channelReduces, String catalogId, Platform platform) {
List<CommonGBChannel> deviceChannelList = new ArrayList<>();
if (!channelReduces.isEmpty()){
PlatformCatalog catalog = catalogManager.selectByPlatFormAndCatalogId(platform.getServerGBId(),catalogId);
if (catalog == null && catalogId.equals(platform.getDeviceGBId())) {
for (ChannelReduce channelReduce : channelReduces) {
DeviceChannel deviceChannel = deviceChannelMapper.getOne(channelReduce.getId());
deviceChannel.setParental(0);
deviceChannel.setCivilCode(platform.getServerGBDomain());
deviceChannelList.add(deviceChannel);
}
return deviceChannelList;
} else if (catalog == null && !catalogId.equals(platform.getDeviceGBId())) {
log.warn("未查询到目录{}的信息", catalogId);
return null;
}
for (ChannelReduce channelReduce : channelReduces) {
DeviceChannel deviceChannel = deviceChannelMapper.getOne(channelReduce.getId());
deviceChannel.setParental(0);
deviceChannel.setCivilCode(catalog.getCivilCode());
deviceChannel.setParentId(catalog.getParentId());
deviceChannel.setBusinessGroupId(catalog.getBusinessGroupId());
deviceChannelList.add(deviceChannel);
}
}
// if (!channelReduces.isEmpty()){
// PlatformCatalog catalog = catalogManager.selectByPlatFormAndCatalogId(platform.getServerGBId(),catalogId);
// if (catalog == null && catalogId.equals(platform.getDeviceGBId())) {
// for (ChannelReduce channelReduce : channelReduces) {
// DeviceChannel deviceChannel = deviceChannelMapper.getOne(channelReduce.getId());
// deviceChannel.setParental(0);
// deviceChannel.setCivilCode(platform.getServerGBDomain());
// deviceChannelList.add(deviceChannel);
// }
// return deviceChannelList;
// } else if (catalog == null && !catalogId.equals(platform.getDeviceGBId())) {
// log.warn("未查询到目录{}的信息", catalogId);
// return null;
// }
// for (ChannelReduce channelReduce : channelReduces) {
// DeviceChannel deviceChannel = deviceChannelMapper.getOne(channelReduce.getId());
// deviceChannel.setParental(0);
// deviceChannel.setCivilCode(catalog.getCivilCode());
// deviceChannel.setParentId(catalog.getParentId());
// deviceChannel.setBusinessGroupId(catalog.getBusinessGroupId());
// deviceChannelList.add(deviceChannel);
// }
// }
return deviceChannelList;
}

View File

@@ -4,28 +4,29 @@ import com.baomidou.dynamic.datasource.annotation.DS;
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.StreamInfo;
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.dao.PlatformMapper;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.gb28181.service.IInviteStreamService;
import com.genersoft.iot.vmp.gb28181.service.IPlatformService;
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.utils.SipUtils;
import com.genersoft.iot.vmp.media.bean.MediaInfo;
import com.genersoft.iot.vmp.media.bean.MediaServer;
import com.genersoft.iot.vmp.media.event.hook.HookData;
import com.genersoft.iot.vmp.media.event.hook.HookSubscribe;
import com.genersoft.iot.vmp.media.event.media.MediaDepartureEvent;
import com.genersoft.iot.vmp.media.event.mediaServer.MediaSendRtpStoppedEvent;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.gb28181.service.IInviteStreamService;
import com.genersoft.iot.vmp.gb28181.service.IPlatformService;
import com.genersoft.iot.vmp.gb28181.service.IPlayService;
import com.genersoft.iot.vmp.service.bean.*;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.dao.GbStreamMapper;
import com.genersoft.iot.vmp.gb28181.dao.PlatformMapper;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
@@ -88,9 +89,6 @@ public class PlatformServiceImpl implements IPlatformService {
@Autowired
private VideoStreamSessionManager streamSession;
@Autowired
private IPlayService playService;
@Autowired
private IInviteStreamService inviteStreamService;
@@ -493,7 +491,7 @@ public class PlatformServiceImpl implements IPlatformService {
if (inviteInfoForOld != null && inviteInfoForOld.getStreamInfo() != null) {
// 如果zlm不存在这个流则删除数据即可
MediaServer mediaServerItemForStreamInfo = mediaServerService.getOne(inviteInfoForOld.getStreamInfo().getMediaServerId());
MediaServer mediaServerItemForStreamInfo = mediaServerService.getOne(inviteInfoForOld.getStreamInfo().getMediaServer().getId());
if (mediaServerItemForStreamInfo != null) {
Boolean ready = mediaServerService.isStreamReady(mediaServerItemForStreamInfo, inviteInfoForOld.getStreamInfo().getApp(), inviteInfoForOld.getStreamInfo().getStream());
if (!ready) {
@@ -567,7 +565,7 @@ public class PlatformServiceImpl implements IPlatformService {
log.info("[国标级联] 发起语音喊话 收到上级推流 deviceId: {}, channelId: {}", platform.getServerGBId(), channelId);
dynamicTask.stop(timeOutTaskKey);
// hook响应
playService.onPublishHandlerForPlay(hookData.getMediaServer(), hookData.getMediaInfo(), platform.getServerGBId(), channelId);
onPublishHandlerForBroadcast(hookData.getMediaServer(), hookData.getMediaInfo(), platform.getServerGBId(), channelId);
// 收到流
if (hookEvent != null) {
hookEvent.response(hookData);
@@ -623,6 +621,18 @@ public class PlatformServiceImpl implements IPlatformService {
});
}
public void onPublishHandlerForBroadcast(MediaServer mediaServerItem, MediaInfo mediaInfo, String platFormServerId, String channelId) {
StreamInfo streamInfo = mediaServerService.getStreamInfoByAppAndStream(mediaServerItem, mediaInfo.getApp(), mediaInfo.getStream(), mediaInfo, null);
streamInfo.setChannelId(channelId);
InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, platFormServerId, channelId);
if (inviteInfo != null) {
inviteInfo.setStatus(InviteSessionStatus.ok);
inviteInfo.setStreamInfo(streamInfo);
inviteStreamService.updateInviteInfo(inviteInfo);
}
}
private void inviteOKHandler(SipSubscribe.EventResult eventResult, SSRCInfo ssrcInfo, int tcpMode, boolean ssrcCheck, MediaServer mediaServerItem,
Platform platform, String channelId, String timeOutTaskKey, ErrorCallback<Object> callback,
InviteInfo inviteInfo, InviteSessionType inviteSessionType){

View File

@@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.gb28181.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.genersoft.iot.vmp.common.InviteInfo;
import com.genersoft.iot.vmp.common.*;
import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.conf.UserSetting;
@@ -8,7 +9,12 @@ import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.conf.exception.ServiceException;
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.controller.bean.AudioBroadcastEvent;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService;
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
import com.genersoft.iot.vmp.gb28181.service.IInviteStreamService;
import com.genersoft.iot.vmp.gb28181.service.IPlayService;
import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager;
import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
@@ -26,10 +32,6 @@ import com.genersoft.iot.vmp.media.event.media.MediaDepartureEvent;
import com.genersoft.iot.vmp.media.event.media.MediaNotFoundEvent;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.media.zlm.SendRtpPortManager;
import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService;
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
import com.genersoft.iot.vmp.gb28181.service.IInviteStreamService;
import com.genersoft.iot.vmp.gb28181.service.IPlayService;
import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
@@ -41,7 +43,6 @@ import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.bean.StreamContent;
import com.genersoft.iot.vmp.gb28181.controller.bean.AudioBroadcastEvent;
import gov.nist.javax.sip.message.SIPResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@@ -55,6 +56,7 @@ import javax.sip.InvalidArgumentException;
import javax.sip.ResponseEvent;
import javax.sip.SipException;
import javax.sip.header.CallIdHeader;
import javax.sip.message.Response;
import java.io.File;
import java.math.BigDecimal;
import java.math.RoundingMode;
@@ -265,7 +267,7 @@ public class PlayServiceImpl implements IPlayService {
@Override
public SSRCInfo play(MediaServer mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<Object> callback) {
public SSRCInfo play(MediaServer mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<StreamInfo> callback) {
if (mediaServerItem == null) {
log.warn("[点播] 未找到可用的zlm deviceId: {},channelId:{}", deviceId, channelId);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到可用的zlm");
@@ -300,8 +302,7 @@ public class PlayServiceImpl implements IPlayService {
null);
return inviteInfo.getSsrcInfo();
}
String mediaServerId = streamInfo.getMediaServerId();
MediaServer mediaInfo = mediaServerService.getOne(mediaServerId);
MediaServer mediaInfo = streamInfo.getMediaServer();
Boolean ready = mediaServerService.isStreamReady(mediaInfo, "rtp", streamId);
if (ready != null && ready) {
callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo);
@@ -465,7 +466,7 @@ public class PlayServiceImpl implements IPlayService {
@Override
public void play(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel,
ErrorCallback<Object> callback) {
ErrorCallback<StreamInfo> callback) {
if (mediaServerItem == null || ssrcInfo == null) {
if (callback != null) {
@@ -608,7 +609,7 @@ public class PlayServiceImpl implements IPlayService {
private void tcpActiveHandler(Device device, String channelId, String contentString,
MediaServer mediaServerItem,
String timeOutTaskKey, SSRCInfo ssrcInfo, ErrorCallback<Object> callback){
String timeOutTaskKey, SSRCInfo ssrcInfo, ErrorCallback<StreamInfo> callback){
if (!device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE")) {
return;
}
@@ -752,7 +753,7 @@ public class PlayServiceImpl implements IPlayService {
@Override
public void playBack(String deviceId, String channelId, String startTime,
String endTime, ErrorCallback<Object> callback) {
String endTime, ErrorCallback<StreamInfo> callback) {
Device device = deviceService.getDeviceByDeviceId(deviceId);
if (device == null) {
log.warn("[录像回放] 未找到设备 deviceId: {},channelId:{}", deviceId, channelId);
@@ -785,7 +786,7 @@ public class PlayServiceImpl implements IPlayService {
@Override
public void playBack(MediaServer mediaServerItem, SSRCInfo ssrcInfo,
String deviceId, String channelId, String startTime,
String endTime, ErrorCallback<Object> callback) {
String endTime, ErrorCallback<StreamInfo> callback) {
if (mediaServerItem == null || ssrcInfo == null) {
callback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(),
InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getMsg(),
@@ -868,7 +869,7 @@ public class PlayServiceImpl implements IPlayService {
private void InviteOKHandler(SipSubscribe.EventResult eventResult, SSRCInfo ssrcInfo, MediaServer mediaServerItem,
Device device, String channelId, String timeOutTaskKey, ErrorCallback<Object> callback,
Device device, String channelId, String timeOutTaskKey, ErrorCallback<StreamInfo> callback,
InviteInfo inviteInfo, InviteSessionType inviteSessionType){
inviteInfo.setStatus(InviteSessionStatus.ok);
ResponseEvent responseEvent = (ResponseEvent) eventResult.event;
@@ -958,7 +959,7 @@ public class PlayServiceImpl implements IPlayService {
@Override
public void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<Object> callback) {
public void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<StreamInfo> callback) {
Device device = deviceService.getDeviceByDeviceId(deviceId);
if (device == null) {
return;
@@ -982,7 +983,7 @@ public class PlayServiceImpl implements IPlayService {
@Override
public void download(MediaServer mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<Object> callback) {
public void download(MediaServer mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<StreamInfo> callback) {
if (mediaServerItem == null || ssrcInfo == null) {
callback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(),
InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getMsg(),
@@ -1092,8 +1093,7 @@ public class PlayServiceImpl implements IPlayService {
}
// 获取当前已下载时长
String mediaServerId = inviteInfo.getStreamInfo().getMediaServerId();
MediaServer mediaServerItem = mediaServerService.getOne(mediaServerId);
MediaServer mediaServerItem = inviteInfo.getStreamInfo().getMediaServer();
if (mediaServerItem == null) {
log.warn("[获取下载进度] 查询录像信息时发现节点不存在");
return null;
@@ -1375,7 +1375,7 @@ public class PlayServiceImpl implements IPlayService {
}
inviteInfo.getStreamInfo().setPause(true);
inviteStreamService.updateInviteInfo(inviteInfo);
MediaServer mediaServerItem = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId());
MediaServer mediaServerItem = inviteInfo.getStreamInfo().getMediaServer();
if (null == mediaServerItem) {
log.warn("mediaServer 不存在!");
throw new ServiceException("mediaServer不存在");
@@ -1403,7 +1403,7 @@ public class PlayServiceImpl implements IPlayService {
}
inviteInfo.getStreamInfo().setPause(false);
inviteStreamService.updateInviteInfo(inviteInfo);
MediaServer mediaServerItem = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId());
MediaServer mediaServerItem = inviteInfo.getStreamInfo().getMediaServer();
if (null == mediaServerItem) {
log.warn("mediaServer 不存在!");
throw new ServiceException("mediaServer不存在");
@@ -1580,7 +1580,7 @@ public class PlayServiceImpl implements IPlayService {
if (inviteInfo != null) {
if (inviteInfo.getStreamInfo() != null) {
// 已存在线直接截图
MediaServer mediaServerItemInuse = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId());
MediaServer mediaServerItemInuse = inviteInfo.getStreamInfo().getMediaServer();
String streamUrl;
if (mediaServerItemInuse.getRtspPort() != 0) {
streamUrl = String.format("rtsp://127.0.0.1:%s/%s/%s", mediaServerItemInuse.getRtspPort(), "rtp", inviteInfo.getStreamInfo().getStream());
@@ -1635,7 +1635,55 @@ public class PlayServiceImpl implements IPlayService {
channelService.stopPlay(device.getDeviceId(), channelId);
channelService.stopPlay(device.getDeviceId(), channelId);
if (inviteInfo.getStreamInfo() != null) {
mediaServerService.closeRTPServer(inviteInfo.getStreamInfo().getMediaServerId(), inviteInfo.getStream());
mediaServerService.closeRTPServer(inviteInfo.getStreamInfo().getMediaServer(), inviteInfo.getStream());
}
}
@Override
public void play(CommonGBChannel channel, ErrorCallback<StreamInfo> callback) {
Device device = deviceService.getDevice(channel.getGbDeviceDbId());
if (device == null) {
log.warn("[点播] 未找到通道{}的设备信息", channel);
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
}
MediaServer mediaServer = getNewMediaServerItem(device);
if (mediaServer == null) {
log.warn("[点播] 未找到可用媒体节点");
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
}
play(mediaServer, device.getDeviceId(), channel.getGbDeviceId(), null, callback);
}
@Override
public void playBack(CommonGBChannel channel, Long startTime, Long stopTime, ErrorCallback<StreamInfo> callback) {
if (startTime == null || stopTime == null) {
throw new PlayException(Response.BAD_REQUEST, "bad request");
}
// 国标通道
Device device = deviceService.getDevice(channel.getGbDeviceDbId());
if (device == null) {
log.warn("[点播] 未找到通道{}的设备信息", channel);
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
}
String startTimeStr = DateUtil.timestampTo_yyyy_MM_dd_HH_mm_ss(startTime);
String stopTimeStr = DateUtil.timestampTo_yyyy_MM_dd_HH_mm_ss(stopTime);
playBack(device.getDeviceId(), channel.getGbDeviceId(), startTimeStr, stopTimeStr, callback);
}
@Override
public void download(CommonGBChannel channel, Long startTime, Long stopTime, Integer downloadSpeed, ErrorCallback<StreamInfo> callback) {
if (startTime == null || stopTime == null || downloadSpeed == null) {
throw new PlayException(Response.BAD_REQUEST, "bad request");
}
// 国标通道
Device device = deviceService.getDevice(channel.getGbDeviceDbId());
if (device == null) {
log.warn("[点播] 未找到通道{}的设备信息", channel);
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
}
String startTimeStr = DateUtil.timestampTo_yyyy_MM_dd_HH_mm_ss(startTime);
String stopTimeStr = DateUtil.timestampTo_yyyy_MM_dd_HH_mm_ss(stopTime);
download(device.getDeviceId(), channel.getGbDeviceId(), startTimeStr, stopTimeStr, downloadSpeed, callback);
}
}

View File

@@ -35,11 +35,9 @@ public class RegionServiceImpl implements IRegionService {
@Autowired
private RegionMapper regionMapper;
@Autowired
private CommonGBChannelMapper commonGBChannelMapper;
@Autowired
private IGbChannelService gbChannelService;

View File

@@ -222,7 +222,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
deviceChannelService.stopPlay(ssrcTransaction.getDeviceId(), channel.getDeviceId());
inviteStreamService.removeInviteInfo(inviteInfo);
if (inviteInfo.getStreamInfo() != null) {
mediaServerService.closeRTPServer(inviteInfo.getStreamInfo().getMediaServerId(), inviteInfo.getStreamInfo().getStream());
mediaServerService.closeRTPServer(inviteInfo.getStreamInfo().getMediaServer(), inviteInfo.getStreamInfo().getStream());
}
}
break;

View File

@@ -9,7 +9,7 @@ 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.bean.*;
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
import com.genersoft.iot.vmp.gb28181.service.IGbChannelPlayService;
import com.genersoft.iot.vmp.gb28181.service.IGbChannelService;
import com.genersoft.iot.vmp.gb28181.service.IPlayService;
import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager;
@@ -34,7 +34,6 @@ import com.genersoft.iot.vmp.service.redisMsg.RedisPushStreamResponseListener;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.streamProxy.service.IStreamProxyService;
import com.genersoft.iot.vmp.streamPush.service.IStreamPushService;
import gov.nist.javax.sdp.TimeDescriptionImpl;
import gov.nist.javax.sdp.fields.TimeField;
import gov.nist.javax.sdp.fields.URIField;
@@ -76,14 +75,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
@Autowired
private IVideoManagerStorage storager;
@Autowired
private IDeviceService deviceService;
@Autowired
private IGbChannelService channelService;
@Autowired
private IStreamPushService streamPushService;
private IGbChannelPlayService channelPlayService;
@Autowired
private IStreamProxyService streamProxyService;
@@ -160,7 +156,6 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
if (platform == null) {
inviteFromDeviceHandle(request, inviteInfo.getRequesterId(), inviteInfo.getChannelId());
} else {
// 查询平台下是否有该通道
CommonGBChannel channel= channelService.queryOneWithPlatform(platform.getId(), inviteInfo.getChannelId());
if (channel == null) {
@@ -184,7 +179,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
log.error("[命令发送失败] 上级Invite TRYING: {}", e.getMessage());
}
channelService.start(channel, inviteInfo, ((code, msg, commonChannelPlayInfo) -> {
channelPlayService.start(channel, inviteInfo, platform, ((code, msg, streamInfo) -> {
if (code != Response.OK) {
try {
responseAck(request, code, msg);
@@ -194,9 +189,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
}else {
// 点播成功, TODO 可以在此处检测cancel命令是否存在存在则不发送
// 构建sendRTP内容
SendRtpItem sendRtpItem = mediaServerService.createSendRtpItem(commonChannelPlayInfo.getMediaServer(),
SendRtpItem sendRtpItem = mediaServerService.createSendRtpItem(streamInfo.getMediaServer(),
inviteInfo.getIp(), inviteInfo.getPort(), inviteInfo.getSsrc(), platform.getServerGBId(),
commonChannelPlayInfo.getStreamInfo().getApp(), commonChannelPlayInfo.getStreamInfo().getStream(),
streamInfo.getApp(), streamInfo.getStream(),
channel.getGbDeviceId(), inviteInfo.isTcp(), platform.isRtcp());
if (inviteInfo.isTcp() && inviteInfo.isTcpActive()) {
sendRtpItem.setTcpActive(true);
@@ -206,7 +201,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
sendRtpItem.setPlayType("Play".equalsIgnoreCase(inviteInfo.getSessionName()) ? InviteStreamType.PLAY : InviteStreamType.PLAYBACK);
redisCatchStorage.updateSendRTPSever(sendRtpItem);
String sdpIp = commonChannelPlayInfo.getMediaServer().getSdpIp();
String sdpIp = streamInfo.getMediaServer().getSdpIp();
if (!ObjectUtils.isEmpty(platform.getSendStreamIp())) {
sdpIp = platform.getSendStreamIp();
}
@@ -214,7 +209,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
// 超时未收到Ack应该回复bye,当前等待时间为10秒
dynamicTask.startDelay(inviteInfo.getCallId(), () -> {
log.info("Ack 等待超时");
mediaServerService.releaseSsrc(commonChannelPlayInfo.getMediaServer().getId(), sendRtpItem.getSsrc());
mediaServerService.releaseSsrc(streamInfo.getMediaServer().getId(), sendRtpItem.getSsrc());
// 回复bye
sendBye(platform, inviteInfo.getCallId());
}, 60 * 1000);