支持支持主码流子码流切换
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
package com.genersoft.iot.vmp.common;
|
||||
|
||||
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
/**
|
||||
* 记录每次发送invite消息的状态
|
||||
@@ -125,20 +124,4 @@ public class InviteInfo {
|
||||
this.streamMode = streamMode;
|
||||
}
|
||||
|
||||
|
||||
/*=========================设备主子码流逻辑START====================*/
|
||||
@Schema(description = "是否为子码流(true-是,false-主码流)")
|
||||
private boolean subStream;
|
||||
|
||||
public boolean isSubStream() {
|
||||
return subStream;
|
||||
}
|
||||
|
||||
public void setSubStream(boolean subStream) {
|
||||
this.subStream = subStream;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -453,19 +453,4 @@ public class Device {
|
||||
this.sipTransactionInfo = sipTransactionInfo;
|
||||
}
|
||||
|
||||
/*======================设备主子码流逻辑START=========================*/
|
||||
@Schema(description = "开启主子码流切换的开关(false-不开启,true-开启)")
|
||||
private boolean switchPrimarySubStream;
|
||||
|
||||
public boolean isSwitchPrimarySubStream() {
|
||||
return switchPrimarySubStream;
|
||||
}
|
||||
|
||||
public void setSwitchPrimarySubStream(boolean switchPrimarySubStream) {
|
||||
this.switchPrimarySubStream = switchPrimarySubStream;
|
||||
}
|
||||
|
||||
/*======================设备主子码流逻辑END=========================*/
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -246,6 +246,10 @@ public class DeviceChannel {
|
||||
@Schema(description = "GPS的更新时间")
|
||||
private String gpsTime;
|
||||
|
||||
@Schema(description = "码流标识,优先级高于设备中码流标识," +
|
||||
"用于选择码流时组成码流标识。默认为null,不设置。可选值: stream/streamnumber/streamprofile/streamMode")
|
||||
private String streamIdentification;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
@@ -574,4 +578,12 @@ public class DeviceChannel {
|
||||
public void setGpsTime(String gpsTime) {
|
||||
this.gpsTime = gpsTime;
|
||||
}
|
||||
|
||||
public String getStreamIdentification() {
|
||||
return streamIdentification;
|
||||
}
|
||||
|
||||
public void setStreamIdentification(String streamIdentification) {
|
||||
this.streamIdentification = streamIdentification;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
/**
|
||||
* 码流索引标识
|
||||
*/
|
||||
public enum GbSteamIdentification {
|
||||
/**
|
||||
* 主码流 stream:0
|
||||
* 子码流 stream:1s
|
||||
*/
|
||||
streamMain("stream", new String[]{"0","1"}),
|
||||
/**
|
||||
* 国标28181-2022定义的方式
|
||||
* 主码流 streamnumber:0
|
||||
* 子码流 streamnumber:1
|
||||
*/
|
||||
streamnumber("streamnumber", new String[]{"0","1"}),
|
||||
/**
|
||||
* 主码流 streamprofile:0
|
||||
* 子码流 streamprofile:1
|
||||
*/
|
||||
streamprofile("streamprofile", new String[]{"0","1"}),
|
||||
/**
|
||||
* 适用的品牌: TP-LINK
|
||||
*/
|
||||
streamMode("streamMode", new String[]{"main","sub"}),
|
||||
;
|
||||
|
||||
GbSteamIdentification(String value, String[] indexArray) {
|
||||
this.value = value;
|
||||
this.indexArray = indexArray;
|
||||
}
|
||||
|
||||
private String value;
|
||||
private String[] indexArray;
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String[] getIndexArray() {
|
||||
return indexArray;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
@@ -96,9 +97,9 @@ public interface ISIPCommander {
|
||||
/**
|
||||
* 请求预览视频流
|
||||
* @param device 视频设备
|
||||
* @param channelId 预览通道
|
||||
* @param channel 预览通道
|
||||
*/
|
||||
void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 请求回放视频流
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
|
||||
import com.genersoft.iot.vmp.gb28181.SipLayer;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
|
||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||
@@ -264,12 +265,12 @@ public class SIPCommander implements ISIPCommander {
|
||||
* 请求预览视频流
|
||||
*
|
||||
* @param device 视频设备
|
||||
* @param channelId 预览通道
|
||||
* @param channel 预览通道
|
||||
* @param event hook订阅
|
||||
* @param errorEvent sip错误订阅
|
||||
*/
|
||||
@Override
|
||||
public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
|
||||
public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel,
|
||||
ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
|
||||
String stream = ssrcInfo.getStream();
|
||||
|
||||
@@ -293,7 +294,7 @@ public class SIPCommander implements ISIPCommander {
|
||||
}
|
||||
StringBuffer content = new StringBuffer(200);
|
||||
content.append("v=0\r\n");
|
||||
content.append("o=" + channelId + " 0 0 IN IP4 " + sdpIp + "\r\n");
|
||||
content.append("o=" + channel.getChannelId() + " 0 0 IN IP4 " + sdpIp + "\r\n");
|
||||
content.append("s=Play\r\n");
|
||||
content.append("c=IN IP4 " + sdpIp + "\r\n");
|
||||
content.append("t=0 0\r\n");
|
||||
@@ -344,20 +345,8 @@ public class SIPCommander implements ISIPCommander {
|
||||
}
|
||||
}
|
||||
|
||||
if( device.isSwitchPrimarySubStream() ){
|
||||
if("TP-LINK".equals(device.getManufacturer())){
|
||||
if (device.isSwitchPrimarySubStream()){
|
||||
content.append("a=streamMode:sub\r\n");
|
||||
}else {
|
||||
content.append("a=streamMode:main\r\n");
|
||||
}
|
||||
}else {
|
||||
if (device.isSwitchPrimarySubStream()){
|
||||
content.append("a=streamprofile:1\r\n");
|
||||
}else {
|
||||
content.append("a=streamprofile:0\r\n");
|
||||
}
|
||||
}
|
||||
if (!ObjectUtils.isEmpty(channel.getStreamIdentification())) {
|
||||
content.append("a=" + channel.getStreamIdentification() + "\r\n");
|
||||
}
|
||||
|
||||
content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
|
||||
@@ -366,16 +355,16 @@ public class SIPCommander implements ISIPCommander {
|
||||
|
||||
|
||||
|
||||
Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
|
||||
Request request = headerProvider.createInviteRequest(device, channel.getChannelId(), content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
|
||||
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> {
|
||||
streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
|
||||
streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
|
||||
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
|
||||
errorEvent.response(e);
|
||||
}), e -> {
|
||||
ResponseEvent responseEvent = (ResponseEvent) e.event;
|
||||
SIPResponse response = (SIPResponse) responseEvent.getResponse();
|
||||
String callId = response.getCallIdHeader().getCallId();
|
||||
streamSession.put(device.getDeviceId(), channelId, callId, stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response,
|
||||
streamSession.put(device.getDeviceId(), channel.getChannelId(), callId, stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response,
|
||||
InviteSessionType.PLAY);
|
||||
okEvent.response(e);
|
||||
});
|
||||
|
||||
@@ -87,4 +87,9 @@ public interface IDeviceChannelService {
|
||||
* 直接批量添加
|
||||
*/
|
||||
void batchAddChannel(List<DeviceChannel> deviceChannels);
|
||||
|
||||
/**
|
||||
* 修改通道的码流类型
|
||||
*/
|
||||
void updateChannelStreamIdentification(DeviceChannel channel);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.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.DeviceChannel;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
||||
@@ -16,7 +17,7 @@ import java.text.ParseException;
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ 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.VideoStreamSessionManager;
|
||||
import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
|
||||
@@ -139,10 +138,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);
|
||||
@@ -486,21 +481,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());
|
||||
|
||||
@@ -15,21 +15,26 @@ 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.VideoStreamSessionManager;
|
||||
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;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.*;
|
||||
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;
|
||||
import com.genersoft.iot.vmp.service.*;
|
||||
import com.genersoft.iot.vmp.service.bean.*;
|
||||
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.ErrorCode;
|
||||
@@ -63,7 +68,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||
private IVideoManagerStorage storager;
|
||||
|
||||
@Autowired
|
||||
private SIPCommander cmder;
|
||||
private ISIPCommander cmder;
|
||||
|
||||
@Autowired
|
||||
private SIPCommanderFroPlatform sipCommanderFroPlatform;
|
||||
@@ -95,15 +100,15 @@ public class PlayServiceImpl implements IPlayService {
|
||||
@Autowired
|
||||
private IDeviceService deviceService;
|
||||
|
||||
@Autowired
|
||||
private IDeviceChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private UserSetting userSetting;
|
||||
|
||||
@Autowired
|
||||
private DynamicTask dynamicTask;
|
||||
|
||||
@Autowired
|
||||
private CloudRecordServiceMapper cloudRecordServiceMapper;
|
||||
|
||||
|
||||
@Override
|
||||
public SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<Object> callback) {
|
||||
@@ -117,6 +122,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) {
|
||||
@@ -165,13 +175,13 @@ public class PlayServiceImpl implements IPlayService {
|
||||
null);
|
||||
return null;
|
||||
}
|
||||
play(mediaServerItem, ssrcInfo, device, channelId, callback);
|
||||
play(mediaServerItem, ssrcInfo, device, channel, callback);
|
||||
return ssrcInfo;
|
||||
}
|
||||
|
||||
|
||||
@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) {
|
||||
@@ -180,110 +190,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);
|
||||
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) {
|
||||
|
||||
@@ -293,15 +302,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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,7 +447,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);
|
||||
@@ -463,8 +472,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(),
|
||||
@@ -881,7 +890,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||
cmder.streamByeCmd(device, ssrcTransaction.getChannelId(),
|
||||
ssrcTransaction.getStream(), null);
|
||||
} catch (InvalidArgumentException | ParseException | SipException |
|
||||
SsrcTransactionNotFoundException e) {
|
||||
SsrcTransactionNotFoundException e) {
|
||||
logger.error("[zlm离线]为正在使用此zlm的设备, 发送BYE失败 {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
@@ -1031,16 +1040,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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -20,11 +20,11 @@ public interface DeviceChannelMapper {
|
||||
@Insert("INSERT INTO wvp_device_channel (channel_id, device_id, name, manufacture, model, owner, civil_code, block, " +
|
||||
"address, parental, parent_id, safety_way, register_way, cert_num, certifiable, err_code, secrecy, " +
|
||||
"ip_address, port, password, ptz_type, status, stream_id, longitude, latitude, longitude_gcj02, latitude_gcj02, " +
|
||||
"longitude_wgs84, latitude_wgs84, has_audio, create_time, update_time, business_group_id, gps_time) " +
|
||||
"longitude_wgs84, latitude_wgs84, has_audio, create_time, update_time, business_group_id, gps_time, stream_identification) " +
|
||||
"VALUES (#{channelId}, #{deviceId}, #{name}, #{manufacture}, #{model}, #{owner}, #{civilCode}, #{block}," +
|
||||
"#{address}, #{parental}, #{parentId}, #{safetyWay}, #{registerWay}, #{certNum}, #{certifiable}, #{errCode}, #{secrecy}, " +
|
||||
"#{ipAddress}, #{port}, #{password}, #{PTZType}, #{status}, #{streamId}, #{longitude}, #{latitude}, #{longitudeGcj02}, " +
|
||||
"#{latitudeGcj02}, #{longitudeWgs84}, #{latitudeWgs84}, #{hasAudio}, #{createTime}, #{updateTime}, #{businessGroupId}, #{gpsTime})")
|
||||
"#{latitudeGcj02}, #{longitudeWgs84}, #{latitudeWgs84}, #{hasAudio}, #{createTime}, #{updateTime}, #{businessGroupId}, #{gpsTime}, #{streamIdentification})")
|
||||
int add(DeviceChannel channel);
|
||||
|
||||
@Update(value = {" <script>" +
|
||||
@@ -60,6 +60,7 @@ public interface DeviceChannelMapper {
|
||||
"<if test='latitudeWgs84 != null'>, latitude_wgs84=#{latitudeWgs84}</if>" +
|
||||
"<if test='businessGroupId != null'>, business_group_id=#{businessGroupId}</if>" +
|
||||
"<if test='gpsTime != null'>, gps_time=#{gpsTime}</if>" +
|
||||
"<if test='streamIdentification != null'>, stream_identification=#{streamIdentification}</if>" +
|
||||
"WHERE device_id=#{deviceId} AND channel_id=#{channelId}"+
|
||||
" </script>"})
|
||||
int update(DeviceChannel channel);
|
||||
@@ -102,6 +103,7 @@ public interface DeviceChannelMapper {
|
||||
"dc.longitude_wgs84, " +
|
||||
"dc.latitude_wgs84, " +
|
||||
"dc.business_group_id, " +
|
||||
"dc.stream_identification, " +
|
||||
"dc.gps_time " +
|
||||
"from " +
|
||||
"wvp_device_channel dc " +
|
||||
@@ -241,7 +243,7 @@ public interface DeviceChannelMapper {
|
||||
"(channel_id, device_id, name, manufacture, model, owner, civil_code, block, sub_count, " +
|
||||
" address, parental, parent_id, safety_way, register_way, cert_num, certifiable, err_code, secrecy, " +
|
||||
" ip_address,port,password,ptz_type,status,stream_id,longitude,latitude,longitude_gcj02,latitude_gcj02,"+
|
||||
" longitude_wgs84,latitude_wgs84,has_audio,create_time,update_time,business_group_id,gps_time)"+
|
||||
" longitude_wgs84,latitude_wgs84,has_audio,create_time,update_time,business_group_id,gps_time,stream_identification)"+
|
||||
"values " +
|
||||
"<foreach collection='addChannels' index='index' item='item' separator=','> " +
|
||||
"(#{item.channelId}, #{item.deviceId}, #{item.name}, #{item.manufacture}, #{item.model}, " +
|
||||
@@ -251,7 +253,7 @@ public interface DeviceChannelMapper {
|
||||
"#{item.ipAddress}, #{item.port}, #{item.password}, #{item.PTZType}, #{item.status}, " +
|
||||
"#{item.streamId}, #{item.longitude}, #{item.latitude},#{item.longitudeGcj02}, " +
|
||||
"#{item.latitudeGcj02},#{item.longitudeWgs84}, #{item.latitudeWgs84}, #{item.hasAudio}, now(), now(), " +
|
||||
"#{item.businessGroupId}, #{item.gpsTime}) " +
|
||||
"#{item.businessGroupId}, #{item.gpsTime}, #{item.streamIdentification}) " +
|
||||
"</foreach> " +
|
||||
"</script>")
|
||||
int batchAdd(@Param("addChannels") List<DeviceChannel> addChannels);
|
||||
@@ -349,6 +351,7 @@ public interface DeviceChannelMapper {
|
||||
"<if test='item.latitudeWgs84 != null'>, latitude_wgs84=#{item.latitudeWgs84}</if>" +
|
||||
"<if test='item.businessGroupId != null'>, business_group_id=#{item.businessGroupId}</if>" +
|
||||
"<if test='item.gpsTime != null'>, gps_time=#{item.gpsTime}</if>" +
|
||||
"<if test='item.streamIdentification != null'>, stream_identification=#{item.streamIdentification}</if>" +
|
||||
"<if test='item.id > 0'>WHERE id=#{item.id}</if>" +
|
||||
"<if test='item.id == 0'>WHERE device_id=#{item.deviceId} AND channel_id=#{item.channelId}</if>" +
|
||||
"</foreach>" +
|
||||
@@ -542,4 +545,9 @@ public interface DeviceChannelMapper {
|
||||
" </script>"})
|
||||
List<DeviceChannel> getSubChannelsByDeviceId(@Param("deviceId") String deviceId, @Param("parentId") String parentId, @Param("onlyCatalog") boolean onlyCatalog);
|
||||
|
||||
@Update("<script>" +
|
||||
"UPDATE wvp_device_channel SET stream_identification=#{streamIdentification} WHERE device_id=#{deviceId}" +
|
||||
" <if test='channelId != null'> and channel_id = #{channelId} </if>" +
|
||||
"</script>")
|
||||
void updateChannelStreamIdentification(DeviceChannel channel);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,6 @@ public interface DeviceMapper {
|
||||
"geo_coord_sys," +
|
||||
"on_line," +
|
||||
"media_server_id," +
|
||||
"switch_primary_sub_stream," +
|
||||
"(SELECT count(0) FROM wvp_device_channel WHERE device_id=wvp_device.device_id) as channel_count "+
|
||||
" FROM wvp_device WHERE device_id = #{deviceId}")
|
||||
Device getDeviceByDeviceId(String deviceId);
|
||||
@@ -159,7 +158,6 @@ public interface DeviceMapper {
|
||||
"geo_coord_sys,"+
|
||||
"on_line,"+
|
||||
"media_server_id,"+
|
||||
"switch_primary_sub_stream switchPrimarySubStream,"+
|
||||
"(SELECT count(0) FROM wvp_device_channel WHERE device_id=de.device_id) as channel_count " +
|
||||
"FROM wvp_device de" +
|
||||
"<if test=\"onLine != null\"> where on_line=${onLine}</if>"+
|
||||
@@ -249,7 +247,6 @@ public interface DeviceMapper {
|
||||
"<if test=\"ssrcCheck != null\">, ssrc_check=#{ssrcCheck}</if>" +
|
||||
"<if test=\"asMessageChannel != null\">, as_message_channel=#{asMessageChannel}</if>" +
|
||||
"<if test=\"geoCoordSys != null\">, geo_coord_sys=#{geoCoordSys}</if>" +
|
||||
"<if test=\"switchPrimarySubStream != null\">, switch_primary_sub_stream=#{switchPrimarySubStream}</if>" +
|
||||
"<if test=\"mediaServerId != null\">, media_server_id=#{mediaServerId}</if>" +
|
||||
"WHERE device_id=#{deviceId}"+
|
||||
" </script>"})
|
||||
@@ -267,8 +264,7 @@ public interface DeviceMapper {
|
||||
"as_message_channel,"+
|
||||
"geo_coord_sys,"+
|
||||
"on_line,"+
|
||||
"media_server_id,"+
|
||||
"switch_primary_sub_stream"+
|
||||
"media_server_id"+
|
||||
") VALUES (" +
|
||||
"#{deviceId}," +
|
||||
"#{name}," +
|
||||
@@ -281,8 +277,7 @@ public interface DeviceMapper {
|
||||
"#{asMessageChannel}," +
|
||||
"#{geoCoordSys}," +
|
||||
"#{onLine}," +
|
||||
"#{mediaServerId}," +
|
||||
"#{switchPrimarySubStream}" +
|
||||
"#{mediaServerId}" +
|
||||
")")
|
||||
void addCustomDevice(Device device);
|
||||
|
||||
|
||||
@@ -264,6 +264,14 @@ public class DeviceQuery {
|
||||
deviceChannelService.updateChannel(deviceId, channel);
|
||||
}
|
||||
|
||||
@Operation(summary = "修改通道的码流类型", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channel", description = "通道信息", required = true)
|
||||
@PostMapping("/channel/stream/identification/update/")
|
||||
public void updateChannelStreamIdentification(DeviceChannel channel){
|
||||
deviceChannelService.updateChannelStreamIdentification(channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改数据流传输模式
|
||||
* @param deviceId 设备id
|
||||
|
||||
Reference in New Issue
Block a user