添加zlm集群支持
This commit is contained in:
@@ -95,20 +95,43 @@ public class SipLayer implements SipListener {
|
||||
tcpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getSipPort(), "TCP");
|
||||
tcpSipProvider = sipStack.createSipProvider(tcpListeningPoint);
|
||||
tcpSipProvider.addSipListener(this);
|
||||
logger.info("Sip Server TCP 启动成功 port {" + sipConfig.getSipPort() + "}");
|
||||
} catch (TransportNotSupportedException | InvalidArgumentException | TooManyListenersException | ObjectInUseException e) {
|
||||
logger.error(String.format("创建SIP服务失败: %s", e.getMessage()));
|
||||
logger.info("Sip Server TCP 启动成功 port {" + sipConfig.getMonitorIp() + ":" + sipConfig.getSipPort() + "}");
|
||||
// } catch (TransportNotSupportedException | InvalidArgumentException | TooManyListenersException | ObjectInUseException e) {
|
||||
// logger.error(String.format("创建SIP服务失败: %s", e.getMessage()));
|
||||
// }
|
||||
} catch (TransportNotSupportedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidArgumentException e) {
|
||||
logger.error("无法使用 [ {}:{} ]作为SIP[ TCP ]服务,可排查: 1. sip.monitor-ip 是否为本机网卡IP; 2. sip.port 是否已被占用"
|
||||
, sipConfig.getMonitorIp(), sipConfig.getSipPort());
|
||||
} catch (TooManyListenersException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ObjectInUseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return tcpSipProvider;
|
||||
}
|
||||
|
||||
@Bean("udpSipProvider")
|
||||
@DependsOn("sipStack")
|
||||
private SipProvider startUdpListener() throws Exception {
|
||||
ListeningPoint udpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getSipPort(), "UDP");
|
||||
SipProvider udpSipProvider = sipStack.createSipProvider(udpListeningPoint);
|
||||
udpSipProvider.addSipListener(this);
|
||||
logger.info("Sip Server UDP 启动成功 port {" + sipConfig.getSipPort() + "}");
|
||||
private SipProvider startUdpListener() {
|
||||
ListeningPoint udpListeningPoint = null;
|
||||
SipProvider udpSipProvider = null;
|
||||
try {
|
||||
udpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getSipPort(), "UDP");
|
||||
udpSipProvider = sipStack.createSipProvider(udpListeningPoint);
|
||||
udpSipProvider.addSipListener(this);
|
||||
} catch (TransportNotSupportedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidArgumentException e) {
|
||||
logger.error("无法使用 [ {}:{} ]作为SIP[ UDP ]服务,可排查: 1. sip.monitor-ip 是否为本机网卡IP; 2. sip.port 是否已被占用"
|
||||
, sipConfig.getMonitorIp(), sipConfig.getSipPort());
|
||||
} catch (TooManyListenersException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ObjectInUseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
logger.info("Sip Server UDP 启动成功 port [" + sipConfig.getMonitorIp() + ":" + sipConfig.getSipPort() + "]");
|
||||
return udpSipProvider;
|
||||
}
|
||||
|
||||
|
||||
@@ -94,6 +94,11 @@ public class Device {
|
||||
*/
|
||||
private String updateTime;
|
||||
|
||||
/**
|
||||
* 设备使用的媒体id, 默认为null
|
||||
*/
|
||||
private String mediaServerId;
|
||||
|
||||
public String getDeviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
@@ -229,4 +234,12 @@ public class Device {
|
||||
public void setUpdateTime(String updateTime) {
|
||||
this.updateTime = updateTime;
|
||||
}
|
||||
|
||||
public String getMediaServerId() {
|
||||
return mediaServerId;
|
||||
}
|
||||
|
||||
public void setMediaServerId(String mediaServerId) {
|
||||
this.mediaServerId = mediaServerId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ public class GbStream extends PlatformGbStream{
|
||||
private String stream;
|
||||
private String gbId;
|
||||
private String name;
|
||||
private String mediaServerId;
|
||||
private double longitude;
|
||||
private double latitude;
|
||||
private String streamType;
|
||||
@@ -77,4 +78,12 @@ public class GbStream extends PlatformGbStream{
|
||||
public void setStatus(boolean status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getMediaServerId() {
|
||||
return mediaServerId;
|
||||
}
|
||||
|
||||
public void setMediaServerId(String mediaServerId) {
|
||||
this.mediaServerId = mediaServerId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,6 +66,11 @@ public class SendRtpItem {
|
||||
*/
|
||||
private int localPort;
|
||||
|
||||
/**
|
||||
* 使用的流媒体
|
||||
*/
|
||||
private String mediaServerId;
|
||||
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
@@ -161,4 +166,12 @@ public class SendRtpItem {
|
||||
public void setTcpActive(boolean tcpActive) {
|
||||
this.tcpActive = tcpActive;
|
||||
}
|
||||
|
||||
public String getMediaServerId() {
|
||||
return mediaServerId;
|
||||
}
|
||||
|
||||
public void setMediaServerId(String mediaServerId) {
|
||||
this.mediaServerId = mediaServerId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@ import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
|
||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||
import org.slf4j.Logger;
|
||||
@@ -32,6 +35,8 @@ public class PlatformNotRegisterEventLister implements ApplicationListener<Platf
|
||||
private IVideoManagerStorager storager;
|
||||
@Autowired
|
||||
private IRedisCatchStorage redisCatchStorage;
|
||||
@Autowired
|
||||
private IMediaServerService mediaServerService;
|
||||
|
||||
@Autowired
|
||||
private SIPCommanderFroPlatform sipCommanderFroPlatform;
|
||||
@@ -62,22 +67,24 @@ public class PlatformNotRegisterEventLister implements ApplicationListener<Platf
|
||||
logger.info("停止[ {} ]的所有推流", event.getPlatformGbID());
|
||||
StringBuilder app = new StringBuilder();
|
||||
StringBuilder stream = new StringBuilder();
|
||||
for (int i = 0; i < sendRtpItems.size(); i++) {
|
||||
for (SendRtpItem sendRtpItem : sendRtpItems) {
|
||||
if (app.length() != 0) {
|
||||
app.append(",");
|
||||
}
|
||||
app.append(sendRtpItems.get(i).getApp());
|
||||
app.append(sendRtpItem.getApp());
|
||||
if (stream.length() != 0) {
|
||||
stream.append(",");
|
||||
}
|
||||
stream.append(sendRtpItems.get(i).getStreamId());
|
||||
redisCatchStorage.deleteSendRTPServer(event.getPlatformGbID(), sendRtpItems.get(i).getChannelId());
|
||||
stream.append(sendRtpItem.getStreamId());
|
||||
redisCatchStorage.deleteSendRTPServer(event.getPlatformGbID(), sendRtpItem.getChannelId());
|
||||
IMediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("vhost", "__defaultVhost__");
|
||||
param.put("app", app.toString());
|
||||
param.put("stream", stream.toString());
|
||||
zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
|
||||
}
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("vhost","__defaultVhost__");
|
||||
param.put("app", app.toString());
|
||||
param.put("stream", stream.toString());
|
||||
zlmrtpServerFactory.stopSendRtpStream(param);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import javax.sip.message.Response;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.response.impl.*;
|
||||
import com.genersoft.iot.vmp.service.IPlayService;
|
||||
@@ -104,6 +105,9 @@ public class SIPProcessorFactory {
|
||||
@Autowired
|
||||
private ZLMRTPServerFactory zlmrtpServerFactory;
|
||||
|
||||
@Autowired
|
||||
private IMediaServerService mediaServerService;
|
||||
|
||||
|
||||
// 注:这里使用注解会导致循环依赖注入,暂用springBean
|
||||
private SipProvider tcpSipProvider;
|
||||
@@ -128,6 +132,7 @@ public class SIPProcessorFactory {
|
||||
processor.setStorager(storager);
|
||||
processor.setRedisCatchStorage(redisCatchStorage);
|
||||
processor.setZlmrtpServerFactory(zlmrtpServerFactory);
|
||||
processor.setMediaServerService(mediaServerService);
|
||||
return processor;
|
||||
} else if (Request.REGISTER.equals(method)) {
|
||||
RegisterRequestProcessor processor = new RegisterRequestProcessor();
|
||||
@@ -148,6 +153,7 @@ public class SIPProcessorFactory {
|
||||
processor.setRequestEvent(evt);
|
||||
processor.setRedisCatchStorage(redisCatchStorage);
|
||||
processor.setZlmrtpServerFactory(zlmrtpServerFactory);
|
||||
processor.setMediaServerService(mediaServerService);
|
||||
return processor;
|
||||
} else if (Request.BYE.equals(method)) {
|
||||
ByeRequestProcessor processor = new ByeRequestProcessor();
|
||||
@@ -155,6 +161,7 @@ public class SIPProcessorFactory {
|
||||
processor.setRedisCatchStorage(redisCatchStorage);
|
||||
processor.setZlmrtpServerFactory(zlmrtpServerFactory);
|
||||
processor.setSIPCommander(cmder);
|
||||
processor.setMediaServerService(mediaServerService);
|
||||
return processor;
|
||||
} else if (Request.CANCEL.equals(method)) {
|
||||
CancelRequestProcessor processor = new CancelRequestProcessor();
|
||||
|
||||
@@ -3,6 +3,8 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
|
||||
/**
|
||||
* @Description:设备能力接口,用于定义设备的控制、查询能力
|
||||
@@ -90,7 +92,7 @@ public interface ISIPCommander {
|
||||
* @param device 视频设备
|
||||
* @param channelId 预览通道
|
||||
*/
|
||||
void playStreamCmd(Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
|
||||
void playStreamCmd(IMediaServerItem mediaServerItem, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
|
||||
|
||||
/**
|
||||
* 请求回放视频流
|
||||
@@ -100,7 +102,7 @@ public interface ISIPCommander {
|
||||
* @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
void playbackStreamCmd(Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
|
||||
void playbackStreamCmd(IMediaServerItem mediaServerItem,Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
|
||||
|
||||
/**
|
||||
* 视频流停止
|
||||
@@ -288,12 +290,4 @@ public interface ISIPCommander {
|
||||
* @return true = 命令发送成功
|
||||
*/
|
||||
boolean alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime);
|
||||
|
||||
|
||||
/**
|
||||
* 释放rtpserver
|
||||
* @param device
|
||||
* @param channelId
|
||||
*/
|
||||
void closeRTPServer(Device device, String channelId);
|
||||
}
|
||||
|
||||
@@ -13,11 +13,10 @@ import com.alibaba.fastjson.JSONObject;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.conf.MediaConfig;
|
||||
import com.genersoft.iot.vmp.conf.UserSetup;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
|
||||
import com.genersoft.iot.vmp.media.zlm.*;
|
||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||
import gov.nist.javax.sip.message.SIPRequest;
|
||||
@@ -37,6 +36,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @Description:设备能力接口,用于定义设备的控制、查询能力
|
||||
@@ -77,12 +77,6 @@ public class SIPCommander implements ISIPCommander {
|
||||
@Autowired
|
||||
private ZLMRTPServerFactory zlmrtpServerFactory;
|
||||
|
||||
@Autowired
|
||||
private ZLMRESTfulUtils zlmresTfulUtils;
|
||||
|
||||
@Autowired
|
||||
private MediaConfig mediaConfig;
|
||||
|
||||
@Autowired
|
||||
private UserSetup userSetup;
|
||||
|
||||
@@ -340,48 +334,45 @@ public class SIPCommander implements ISIPCommander {
|
||||
* @param errorEvent sip错误订阅
|
||||
*/
|
||||
@Override
|
||||
public void playStreamCmd(Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent) {
|
||||
public void playStreamCmd(IMediaServerItem mediaServerItem, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent) {
|
||||
String streamId = null;
|
||||
try {
|
||||
if (device == null) return;
|
||||
String streamMode = device.getStreamMode().toUpperCase();
|
||||
|
||||
String ssrc = streamSession.createPlaySsrc();
|
||||
if (mediaConfig.isRtpEnable()) {
|
||||
if (mediaServerItem.isRtpEnable()) {
|
||||
streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
|
||||
}else {
|
||||
streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
|
||||
}
|
||||
String streamMode = device.getStreamMode().toUpperCase();
|
||||
ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
|
||||
if (mediaInfo == null) {
|
||||
logger.warn("点播时发现ZLM尚未连接...");
|
||||
return;
|
||||
}
|
||||
Integer mediaPort = null;
|
||||
// 使用动态udp端口
|
||||
if (mediaConfig.isRtpEnable()) {
|
||||
mediaPort = zlmrtpServerFactory.createRTPServer(streamId);
|
||||
if (mediaServerItem.isRtpEnable()) {
|
||||
mediaPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId);
|
||||
}else {
|
||||
mediaPort = mediaInfo.getRtpProxyPort();
|
||||
mediaPort = mediaServerItem.getRtpProxyPort();
|
||||
}
|
||||
|
||||
logger.info("{} 分配的ZLM为: {} [{}:{}]", streamId, mediaServerItem.getId(), mediaServerItem.getIp(), mediaPort);
|
||||
// 添加订阅
|
||||
JSONObject subscribeKey = new JSONObject();
|
||||
subscribeKey.put("app", "rtp");
|
||||
subscribeKey.put("stream", streamId);
|
||||
subscribeKey.put("regist", true);
|
||||
|
||||
subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, json->{
|
||||
subscribeKey.put("mediaServerId", mediaServerItem.getId());
|
||||
subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
|
||||
(IMediaServerItem mediaServerItemInUse, JSONObject json)->{
|
||||
if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
|
||||
event.response(json);
|
||||
event.response(mediaServerItemInUse, json);
|
||||
subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
|
||||
});
|
||||
//
|
||||
StringBuffer content = new StringBuffer(200);
|
||||
content.append("v=0\r\n");
|
||||
// content.append("o=" + sipConfig.getSipId() + " 0 0 IN IP4 "+mediaInfo.getWanIp()+"\r\n");
|
||||
content.append("o="+"00000"+" 0 0 IN IP4 "+mediaInfo.getSdpIp()+"\r\n");
|
||||
content.append("o="+"00000"+" 0 0 IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");
|
||||
content.append("s=Play\r\n");
|
||||
content.append("c=IN IP4 "+mediaInfo.getSdpIp()+"\r\n");
|
||||
content.append("c=IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");
|
||||
content.append("t=0 0\r\n");
|
||||
|
||||
if (userSetup.isSeniorSdp()) {
|
||||
@@ -459,21 +450,32 @@ public class SIPCommander implements ISIPCommander {
|
||||
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
@Override
|
||||
public void playbackStreamCmd(Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event
|
||||
public void playbackStreamCmd(IMediaServerItem mediaServerItem,Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event
|
||||
, SipSubscribe.Event errorEvent) {
|
||||
try {
|
||||
ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
|
||||
String ssrc = streamSession.createPlayBackSsrc();
|
||||
String streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
|
||||
|
||||
Integer mediaPort = null;
|
||||
// 使用动态udp端口
|
||||
if (mediaServerItem.isRtpEnable()) {
|
||||
mediaPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId);
|
||||
}else {
|
||||
mediaPort = mediaServerItem.getRtpProxyPort();
|
||||
}
|
||||
logger.info("{} 分配的ZLM为: {} [{}:{}]", streamId, mediaServerItem.getId(), mediaServerItem.getIp(), mediaPort);
|
||||
|
||||
// 添加订阅
|
||||
JSONObject subscribeKey = new JSONObject();
|
||||
subscribeKey.put("app", "rtp");
|
||||
subscribeKey.put("stream", streamId);
|
||||
subscribeKey.put("regist", true);
|
||||
subscribeKey.put("mediaServerId", mediaServerItem.getId());
|
||||
logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString());
|
||||
subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, json->{
|
||||
subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
|
||||
(IMediaServerItem mediaServerItemInUse, JSONObject json)->{
|
||||
if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
|
||||
event.response(json);
|
||||
event.response(mediaServerItemInUse, json);
|
||||
subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
|
||||
});
|
||||
|
||||
@@ -482,16 +484,12 @@ public class SIPCommander implements ISIPCommander {
|
||||
content.append("o="+sipConfig.getSipId()+" 0 0 IN IP4 "+sipConfig.getSipIp()+"\r\n");
|
||||
content.append("s=Playback\r\n");
|
||||
content.append("u="+channelId+":0\r\n");
|
||||
content.append("c=IN IP4 "+mediaInfo.getSdpIp()+"\r\n");
|
||||
content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n");
|
||||
content.append("t="+DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime)+" "
|
||||
+DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) +"\r\n");
|
||||
Integer mediaPort = null;
|
||||
// 使用动态udp端口
|
||||
if (mediaConfig.isRtpEnable()) {
|
||||
mediaPort = zlmrtpServerFactory.createRTPServer(streamId);
|
||||
}else {
|
||||
mediaPort = mediaInfo.getRtpProxyPort();
|
||||
}
|
||||
|
||||
|
||||
|
||||
String streamMode = device.getStreamMode().toUpperCase();
|
||||
|
||||
if (userSetup.isSeniorSdp()) {
|
||||
@@ -560,56 +558,63 @@ public class SIPCommander implements ISIPCommander {
|
||||
|
||||
|
||||
/**
|
||||
* 视频流停止
|
||||
*
|
||||
* 视频流停止, 不使用回调
|
||||
*/
|
||||
@Override
|
||||
public void streamByeCmd(String deviceId, String channelId) {
|
||||
streamByeCmd(deviceId, channelId, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 视频流停止
|
||||
*/
|
||||
@Override
|
||||
public void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent) {
|
||||
|
||||
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
|
||||
try {
|
||||
ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId);
|
||||
// 服务重启后, 无法直接发送bye, 通过手动构建发送
|
||||
// if (transaction == null) {
|
||||
//
|
||||
// if (streamInfo != null) {
|
||||
// MediaServerItem mediaServerItem = redisCatchStorage.getMediaInfo(streamInfo.getMediaServerId());
|
||||
// JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaServerItem,streamInfo.getApp(), streamInfo.getStreamId());
|
||||
// if (mediaList != null) { // 仍在推流才发送
|
||||
// if (mediaList.getInteger("code") == 0) {
|
||||
// JSONArray data = mediaList.getJSONArray("data");
|
||||
// if (data != null && data.size() > 0) {
|
||||
// Device device = storager.queryVideoDevice(deviceId);
|
||||
// if (device != null) {
|
||||
// StreamInfo.TransactionInfo transactionInfo = streamInfo.getTransactionInfo();
|
||||
// try {
|
||||
// Request byteRequest = headerProvider.createByteRequest(device, channelId,
|
||||
// transactionInfo.branch,
|
||||
// transactionInfo.localTag,
|
||||
// transactionInfo.remoteTag,
|
||||
// transactionInfo.callId);
|
||||
// transmitRequest(device, byteRequest);
|
||||
// } catch (InvalidArgumentException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// redisCatchStorage.stopPlay(streamInfo);
|
||||
// }
|
||||
//
|
||||
// if (okEvent != null) {
|
||||
// okEvent.response(null);
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
if (transaction == null) {
|
||||
|
||||
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
|
||||
if (streamInfo != null) {
|
||||
JSONObject mediaList = zlmresTfulUtils.getMediaList(streamInfo.getApp(), streamInfo.getStreamId());
|
||||
if (mediaList != null) { // 仍在推流才发送
|
||||
if (mediaList.getInteger("code") == 0) {
|
||||
JSONArray data = mediaList.getJSONArray("data");
|
||||
if (data != null && data.size() > 0) {
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
if (device != null) {
|
||||
StreamInfo.TransactionInfo transactionInfo = streamInfo.getTransactionInfo();
|
||||
try {
|
||||
Request byteRequest = headerProvider.createByteRequest(device, channelId,
|
||||
transactionInfo.branch,
|
||||
transactionInfo.localTag,
|
||||
transactionInfo.remoteTag,
|
||||
transactionInfo.callId);
|
||||
transmitRequest(device, byteRequest);
|
||||
} catch (InvalidArgumentException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
redisCatchStorage.stopPlay(streamInfo);
|
||||
}
|
||||
|
||||
if (okEvent != null) {
|
||||
okEvent.response(null);
|
||||
}
|
||||
logger.warn("[ {} -> {}]停止视频流的时候发现事务已丢失", deviceId, channelId);
|
||||
return;
|
||||
}
|
||||
|
||||
Dialog dialog = transaction.getDialog();
|
||||
if (dialog == null) {
|
||||
logger.warn("[ {} -> {}]停止视频流的时候发现对话已丢失", deviceId, channelId);
|
||||
return;
|
||||
}
|
||||
Request byeRequest = dialog.createRequest(Request.BYE);
|
||||
@@ -632,7 +637,7 @@ public class SIPCommander implements ISIPCommander {
|
||||
}
|
||||
|
||||
dialog.sendRequest(clientTransaction);
|
||||
zlmrtpServerFactory.closeRTPServer(streamSession.getStreamId(deviceId, channelId));
|
||||
|
||||
streamSession.remove(deviceId, channelId);
|
||||
} catch (SipException | ParseException e) {
|
||||
e.printStackTrace();
|
||||
@@ -721,7 +726,7 @@ public class SIPCommander implements ISIPCommander {
|
||||
cmdXml.append("<Control>\r\n");
|
||||
cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
|
||||
cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
|
||||
if (XmlUtil.isEmpty(channelId)) {
|
||||
if (StringUtils.isEmpty(channelId)) {
|
||||
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||
} else {
|
||||
cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
|
||||
@@ -821,16 +826,16 @@ public class SIPCommander implements ISIPCommander {
|
||||
cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
|
||||
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||
cmdXml.append("<AlarmCmd>ResetAlarm</AlarmCmd>\r\n");
|
||||
if (!XmlUtil.isEmpty(alarmMethod) || !XmlUtil.isEmpty(alarmType)) {
|
||||
if (!StringUtils.isEmpty(alarmMethod) || !StringUtils.isEmpty(alarmType)) {
|
||||
cmdXml.append("<Info>\r\n");
|
||||
}
|
||||
if (!XmlUtil.isEmpty(alarmMethod)) {
|
||||
if (!StringUtils.isEmpty(alarmMethod)) {
|
||||
cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n");
|
||||
}
|
||||
if (!XmlUtil.isEmpty(alarmType)) {
|
||||
if (!StringUtils.isEmpty(alarmType)) {
|
||||
cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n");
|
||||
}
|
||||
if (!XmlUtil.isEmpty(alarmMethod) || !XmlUtil.isEmpty(alarmType)) {
|
||||
if (!StringUtils.isEmpty(alarmMethod) || !StringUtils.isEmpty(alarmType)) {
|
||||
cmdXml.append("</Info>\r\n");
|
||||
}
|
||||
cmdXml.append("</Control>\r\n");
|
||||
@@ -863,7 +868,7 @@ public class SIPCommander implements ISIPCommander {
|
||||
cmdXml.append("<Control>\r\n");
|
||||
cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
|
||||
cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
|
||||
if (XmlUtil.isEmpty(channelId)) {
|
||||
if (StringUtils.isEmpty(channelId)) {
|
||||
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||
} else {
|
||||
cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
|
||||
@@ -901,7 +906,7 @@ public class SIPCommander implements ISIPCommander {
|
||||
cmdXml.append("<Control>\r\n");
|
||||
cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
|
||||
cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
|
||||
if (XmlUtil.isEmpty(channelId)) {
|
||||
if (StringUtils.isEmpty(channelId)) {
|
||||
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||
} else {
|
||||
cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
|
||||
@@ -969,13 +974,13 @@ public class SIPCommander implements ISIPCommander {
|
||||
cmdXml.append("<Control>\r\n");
|
||||
cmdXml.append("<CmdType>DeviceConfig</CmdType>\r\n");
|
||||
cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
|
||||
if (XmlUtil.isEmpty(channelId)) {
|
||||
if (StringUtils.isEmpty(channelId)) {
|
||||
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||
} else {
|
||||
cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
|
||||
}
|
||||
cmdXml.append("<BasicParam>\r\n");
|
||||
if (!XmlUtil.isEmpty(name)) {
|
||||
if (!StringUtils.isEmpty(name)) {
|
||||
cmdXml.append("<Name>" + name + "</Name>\r\n");
|
||||
}
|
||||
if (NumericUtil.isInteger(expiration)) {
|
||||
@@ -1169,22 +1174,22 @@ public class SIPCommander implements ISIPCommander {
|
||||
cmdXml.append("<CmdType>Alarm</CmdType>\r\n");
|
||||
cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
|
||||
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||
if (!XmlUtil.isEmpty(startPriority)) {
|
||||
if (!StringUtils.isEmpty(startPriority)) {
|
||||
cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n");
|
||||
}
|
||||
if (!XmlUtil.isEmpty(endPriority)) {
|
||||
if (!StringUtils.isEmpty(endPriority)) {
|
||||
cmdXml.append("<EndAlarmPriority>" + endPriority + "</EndAlarmPriority>\r\n");
|
||||
}
|
||||
if (!XmlUtil.isEmpty(alarmMethod)) {
|
||||
if (!StringUtils.isEmpty(alarmMethod)) {
|
||||
cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n");
|
||||
}
|
||||
if (!XmlUtil.isEmpty(alarmType)) {
|
||||
if (!StringUtils.isEmpty(alarmType)) {
|
||||
cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n");
|
||||
}
|
||||
if (!XmlUtil.isEmpty(startTime)) {
|
||||
if (!StringUtils.isEmpty(startTime)) {
|
||||
cmdXml.append("<StartAlarmTime>" + startTime + "</StartAlarmTime>\r\n");
|
||||
}
|
||||
if (!XmlUtil.isEmpty(endTime)) {
|
||||
if (!StringUtils.isEmpty(endTime)) {
|
||||
cmdXml.append("<EndAlarmTime>" + endTime + "</EndAlarmTime>\r\n");
|
||||
}
|
||||
cmdXml.append("</Query>\r\n");
|
||||
@@ -1218,7 +1223,7 @@ public class SIPCommander implements ISIPCommander {
|
||||
cmdXml.append("<Query>\r\n");
|
||||
cmdXml.append("<CmdType>ConfigDownload</CmdType>\r\n");
|
||||
cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
|
||||
if (XmlUtil.isEmpty(channelId)) {
|
||||
if (StringUtils.isEmpty(channelId)) {
|
||||
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||
} else {
|
||||
cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
|
||||
@@ -1253,7 +1258,7 @@ public class SIPCommander implements ISIPCommander {
|
||||
cmdXml.append("<Query>\r\n");
|
||||
cmdXml.append("<CmdType>PresetQuery</CmdType>\r\n");
|
||||
cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
|
||||
if (XmlUtil.isEmpty(channelId)) {
|
||||
if (StringUtils.isEmpty(channelId)) {
|
||||
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||
} else {
|
||||
cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
|
||||
@@ -1365,22 +1370,22 @@ public class SIPCommander implements ISIPCommander {
|
||||
cmdXml.append("<CmdType>Alarm</CmdType>\r\n");
|
||||
cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
|
||||
cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||
if (!XmlUtil.isEmpty(startPriority)) {
|
||||
if (!StringUtils.isEmpty(startPriority)) {
|
||||
cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n");
|
||||
}
|
||||
if (!XmlUtil.isEmpty(endPriority)) {
|
||||
if (!StringUtils.isEmpty(endPriority)) {
|
||||
cmdXml.append("<EndAlarmPriority>" + endPriority + "</EndAlarmPriority>\r\n");
|
||||
}
|
||||
if (!XmlUtil.isEmpty(alarmMethod)) {
|
||||
if (!StringUtils.isEmpty(alarmMethod)) {
|
||||
cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n");
|
||||
}
|
||||
if (!XmlUtil.isEmpty(alarmType)) {
|
||||
if (!StringUtils.isEmpty(alarmType)) {
|
||||
cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n");
|
||||
}
|
||||
if (!XmlUtil.isEmpty(startTime)) {
|
||||
if (!StringUtils.isEmpty(startTime)) {
|
||||
cmdXml.append("<StartAlarmTime>" + startTime + "</StartAlarmTime>\r\n");
|
||||
}
|
||||
if (!XmlUtil.isEmpty(endTime)) {
|
||||
if (!StringUtils.isEmpty(endTime)) {
|
||||
cmdXml.append("<EndAlarmTime>" + endTime + "</EndAlarmTime>\r\n");
|
||||
}
|
||||
cmdXml.append("</Query>\r\n");
|
||||
@@ -1431,16 +1436,4 @@ public class SIPCommander implements ISIPCommander {
|
||||
clientTransaction.sendRequest();
|
||||
return clientTransaction;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void closeRTPServer(Device device, String channelId) {
|
||||
if (mediaConfig.isRtpEnable()) {
|
||||
String streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
|
||||
zlmrtpServerFactory.closeRTPServer(streamId);
|
||||
}
|
||||
streamSession.remove(device.getDeviceId(), channelId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ import javax.sip.message.Request;
|
||||
import gov.nist.javax.sip.SipStackImpl;
|
||||
import gov.nist.javax.sip.message.SIPRequest;
|
||||
import gov.nist.javax.sip.stack.SIPServerTransaction;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* @Description:处理接收IPCamera发来的SIP协议请求消息
|
||||
@@ -24,6 +26,8 @@ import gov.nist.javax.sip.stack.SIPServerTransaction;
|
||||
*/
|
||||
public abstract class SIPRequestAbstractProcessor implements ISIPRequestProcessor {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(SIPRequestAbstractProcessor.class);
|
||||
|
||||
protected RequestEvent evt;
|
||||
|
||||
private SipProvider tcpSipProvider;
|
||||
@@ -64,9 +68,9 @@ public abstract class SIPRequestAbstractProcessor implements ISIPRequestProcesso
|
||||
}
|
||||
}
|
||||
} catch (TransactionAlreadyExistsException e) {
|
||||
e.printStackTrace();
|
||||
logger.error(e.getMessage());
|
||||
} catch (TransactionUnavailableException e) {
|
||||
e.printStackTrace();
|
||||
logger.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
return serverTransaction;
|
||||
|
||||
@@ -13,6 +13,9 @@ import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -30,6 +33,8 @@ public class AckRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
|
||||
private ZLMRTPServerFactory zlmrtpServerFactory;
|
||||
|
||||
private IMediaServerService mediaServerService;
|
||||
|
||||
/**
|
||||
* 处理 ACK请求
|
||||
*
|
||||
@@ -76,18 +81,22 @@ public class AckRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
while (!rtpPushed) {
|
||||
try {
|
||||
if (System.currentTimeMillis() - startTime < 30 * 1000) {
|
||||
if (zlmrtpServerFactory.isStreamReady(streamInfo.getApp(), streamInfo.getStreamId())) {
|
||||
IMediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
|
||||
if (zlmrtpServerFactory.isStreamReady(mediaInfo, streamInfo.getApp(), streamInfo.getStreamId())) {
|
||||
rtpPushed = true;
|
||||
logger.info("已获取设备推流,开始向上级推流");
|
||||
zlmrtpServerFactory.startSendRtpStream(param);
|
||||
logger.info("已获取设备推流[{}/{}],开始向上级推流[{}:{}]",
|
||||
streamInfo.getApp() ,streamInfo.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort());
|
||||
zlmrtpServerFactory.startSendRtpStream(mediaInfo, param);
|
||||
} else {
|
||||
logger.info("等待设备推流.......");
|
||||
logger.info("等待设备推流[{}/{}].......",
|
||||
streamInfo.getApp() ,streamInfo.getStreamId());
|
||||
Thread.sleep(1000);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
rtpPushed = true;
|
||||
logger.info("设备推流超时,终止向上级推流");
|
||||
logger.info("设备推流[{}/{}]超时,终止向上级推流",
|
||||
streamInfo.getApp() ,streamInfo.getStreamId());
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
@@ -123,4 +132,12 @@ public class AckRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
public void setZlmrtpServerFactory(ZLMRTPServerFactory zlmrtpServerFactory) {
|
||||
this.zlmrtpServerFactory = zlmrtpServerFactory;
|
||||
}
|
||||
|
||||
public IMediaServerService getMediaServerService() {
|
||||
return mediaServerService;
|
||||
}
|
||||
|
||||
public void setMediaServerService(IMediaServerService mediaServerService) {
|
||||
this.mediaServerService = mediaServerService;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,9 @@ import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -38,6 +41,8 @@ public class ByeRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
|
||||
private ZLMRTPServerFactory zlmrtpServerFactory;
|
||||
|
||||
private IMediaServerService mediaServerService;
|
||||
|
||||
/**
|
||||
* 处理BYE请求
|
||||
* @param evt
|
||||
@@ -60,9 +65,10 @@ public class ByeRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
param.put("stream",streamId);
|
||||
param.put("ssrc",sendRtpItem.getSsrc());
|
||||
logger.info("停止向上级推流:" + streamId);
|
||||
zlmrtpServerFactory.stopSendRtpStream(param);
|
||||
IMediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
|
||||
zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
|
||||
redisCatchStorage.deleteSendRTPServer(platformGbId, channelId);
|
||||
if (zlmrtpServerFactory.totalReaderCount(sendRtpItem.getApp(), streamId) == 0) {
|
||||
if (zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId) == 0) {
|
||||
logger.info(streamId + "无其它观看者,通知设备停止推流");
|
||||
cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId);
|
||||
}
|
||||
@@ -112,4 +118,11 @@ public class ByeRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
this.cmder = cmder;
|
||||
}
|
||||
|
||||
public IMediaServerService getMediaServerService() {
|
||||
return mediaServerService;
|
||||
}
|
||||
|
||||
public void setMediaServerService(IMediaServerService mediaServerService) {
|
||||
this.mediaServerService = mediaServerService;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,12 +11,16 @@ import javax.sip.header.*;
|
||||
import javax.sip.message.Request;
|
||||
import javax.sip.message.Response;
|
||||
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||
import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
|
||||
@@ -51,6 +55,8 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
|
||||
private ZLMRTPServerFactory zlmrtpServerFactory;
|
||||
|
||||
private IMediaServerService mediaServerService;
|
||||
|
||||
public ZLMRTPServerFactory getZlmrtpServerFactory() {
|
||||
return zlmrtpServerFactory;
|
||||
}
|
||||
@@ -91,6 +97,7 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
// 查询平台下是否有该通道
|
||||
DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId);
|
||||
GbStream gbStream = storager.queryStreamInParentPlatform(requesterId, channelId);
|
||||
IMediaServerItem mediaServerItem = null;
|
||||
// 不是通道可能是直播流
|
||||
if (channel != null && gbStream == null ) {
|
||||
if (channel.getStatus() == 0) {
|
||||
@@ -100,8 +107,15 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
}
|
||||
responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 通道存在,发181,呼叫转接中
|
||||
}else if(channel == null && gbStream != null){
|
||||
Boolean streamReady = zlmrtpServerFactory.isStreamReady(gbStream.getApp(), gbStream.getStream());
|
||||
if (!streamReady) {
|
||||
String mediaServerId = gbStream.getMediaServerId();
|
||||
mediaServerItem = mediaServerService.getOne(mediaServerId);
|
||||
if (mediaServerItem == null) {
|
||||
logger.info("[ app={}, stream={} ]zlm找不到,返回410",gbStream.getApp(), gbStream.getStream());
|
||||
responseAck(evt, Response.GONE, "media server not found");
|
||||
return;
|
||||
}
|
||||
Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream());
|
||||
if (!streamReady ) {
|
||||
logger.info("[ app={}, stream={} ]通道离线,返回400",gbStream.getApp(), gbStream.getStream());
|
||||
responseAck(evt, Response.BAD_REQUEST, "channel [" + gbStream.getGbId() + "] offline");
|
||||
return;
|
||||
@@ -130,8 +144,8 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
//boolean recvonly = false;
|
||||
boolean mediaTransmissionTCP = false;
|
||||
Boolean tcpActive = null;
|
||||
for (int i = 0; i < mediaDescriptions.size(); i++) {
|
||||
MediaDescription mediaDescription = (MediaDescription)mediaDescriptions.get(i);
|
||||
for (Object description : mediaDescriptions) {
|
||||
MediaDescription mediaDescription = (MediaDescription) description;
|
||||
Media media = mediaDescription.getMedia();
|
||||
|
||||
Vector mediaFormats = media.getMediaFormats(false);
|
||||
@@ -147,7 +161,7 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
mediaTransmissionTCP = true;
|
||||
if ("active".equals(setup)) {
|
||||
tcpActive = true;
|
||||
}else if ("passive".equals(setup)) {
|
||||
} else if ("passive".equals(setup)) {
|
||||
tcpActive = false;
|
||||
}
|
||||
}
|
||||
@@ -174,7 +188,13 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
responseAck(evt, Response.SERVER_INTERNAL_ERROR);
|
||||
return;
|
||||
}
|
||||
SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(addressStr, port, ssrc, requesterId,
|
||||
mediaServerItem = playService.getNewMediaServerItem(device);
|
||||
if (mediaServerItem == null) {
|
||||
logger.warn("未找到可用的zlm");
|
||||
responseAck(evt, Response.BUSY_HERE);
|
||||
return;
|
||||
}
|
||||
SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
|
||||
device.getDeviceId(), channelId,
|
||||
mediaTransmissionTCP);
|
||||
if (tcpActive != null) {
|
||||
@@ -189,18 +209,18 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
// 写入redis, 超时时回复
|
||||
redisCatchStorage.updateSendRTPSever(sendRtpItem);
|
||||
// 通知下级推流,
|
||||
PlayResult playResult = playService.play(device.getDeviceId(), channelId, (responseJSON)->{
|
||||
PlayResult playResult = playService.play(mediaServerItem,device.getDeviceId(), channelId, (mediaServerItemInUSe, responseJSON)->{
|
||||
// 收到推流, 回复200OK, 等待ack
|
||||
// if (sendRtpItem == null) return;
|
||||
sendRtpItem.setStatus(1);
|
||||
redisCatchStorage.updateSendRTPSever(sendRtpItem);
|
||||
// TODO 添加对tcp的支持
|
||||
ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
|
||||
|
||||
StringBuffer content = new StringBuffer(200);
|
||||
content.append("v=0\r\n");
|
||||
content.append("o="+"00000"+" 0 0 IN IP4 "+mediaInfo.getSdpIp()+"\r\n");
|
||||
content.append("o="+"00000"+" 0 0 IN IP4 "+mediaServerItemInUSe.getSdpIp()+"\r\n");
|
||||
content.append("s=Play\r\n");
|
||||
content.append("c=IN IP4 "+mediaInfo.getSdpIp()+"\r\n");
|
||||
content.append("c=IN IP4 "+mediaServerItemInUSe.getSdpIp()+"\r\n");
|
||||
content.append("t=0 0\r\n");
|
||||
content.append("m=video "+ sendRtpItem.getLocalPort()+" RTP/AVP 96\r\n");
|
||||
content.append("a=sendonly\r\n");
|
||||
@@ -217,7 +237,7 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} ,(event -> {
|
||||
} ,((event) -> {
|
||||
// 未知错误。直接转发设备点播的错误
|
||||
Response response = null;
|
||||
try {
|
||||
@@ -232,7 +252,7 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
}
|
||||
|
||||
}else if (gbStream != null) {
|
||||
SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(addressStr, port, ssrc, requesterId,
|
||||
SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
|
||||
gbStream.getApp(), gbStream.getStream(), channelId,
|
||||
mediaTransmissionTCP);
|
||||
|
||||
@@ -251,12 +271,11 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
sendRtpItem.setStatus(1);
|
||||
redisCatchStorage.updateSendRTPSever(sendRtpItem);
|
||||
// TODO 添加对tcp的支持
|
||||
ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
|
||||
StringBuffer content = new StringBuffer(200);
|
||||
content.append("v=0\r\n");
|
||||
content.append("o="+"00000"+" 0 0 IN IP4 "+mediaInfo.getSdpIp()+"\r\n");
|
||||
content.append("o="+"00000"+" 0 0 IN IP4 "+mediaServerItem.getSdpIp()+"\r\n");
|
||||
content.append("s=Play\r\n");
|
||||
content.append("c=IN IP4 "+mediaInfo.getSdpIp()+"\r\n");
|
||||
content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n");
|
||||
content.append("t=0 0\r\n");
|
||||
content.append("m=video "+ sendRtpItem.getLocalPort()+" RTP/AVP 96\r\n");
|
||||
content.append("a=sendonly\r\n");
|
||||
@@ -444,4 +463,12 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) {
|
||||
this.redisCatchStorage = redisCatchStorage;
|
||||
}
|
||||
|
||||
public IMediaServerService getMediaServerService() {
|
||||
return mediaServerService;
|
||||
}
|
||||
|
||||
public void setMediaServerService(IMediaServerService mediaServerService) {
|
||||
this.mediaServerService = mediaServerService;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,7 +282,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
//String result = XmlUtil.getText(rootElement, "Result");
|
||||
// 回复200 OK
|
||||
responseAck(evt);
|
||||
if (rootElement.getName().equals("Response")) {//} !XmlUtil.isEmpty(result)) {
|
||||
if (rootElement.getName().equals("Response")) {//} !StringUtils.isEmpty(result)) {
|
||||
// 此处是对本平台发出DeviceControl指令的应答
|
||||
JSONObject json = new JSONObject();
|
||||
XmlUtil.node2Json(rootElement, json);
|
||||
@@ -299,7 +299,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
String platformId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
|
||||
String targetGBId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
|
||||
// 远程启动功能
|
||||
if (!XmlUtil.isEmpty(XmlUtil.getText(rootElement, "TeleBoot"))) {
|
||||
if (!StringUtils.isEmpty(XmlUtil.getText(rootElement, "TeleBoot"))) {
|
||||
if (deviceId.equals(targetGBId)) {
|
||||
// 远程启动本平台:需要在重新启动程序后先对SipStack解绑
|
||||
logger.info("执行远程启动本平台命令");
|
||||
@@ -337,7 +337,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
}
|
||||
}
|
||||
// 云台/前端控制命令
|
||||
if (!XmlUtil.isEmpty(XmlUtil.getText(rootElement,"PTZCmd")) && !deviceId.equals(targetGBId)) {
|
||||
if (!StringUtils.isEmpty(XmlUtil.getText(rootElement,"PTZCmd")) && !deviceId.equals(targetGBId)) {
|
||||
String cmdString = XmlUtil.getText(rootElement,"PTZCmd");
|
||||
Device device = storager.queryVideoDeviceByPlatformIdAndChannelId(platformId, deviceId);
|
||||
cmder.fronEndCmd(device, deviceId, cmdString);
|
||||
@@ -421,7 +421,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
String deviceId = XmlUtil.getText(rootElement, "DeviceID");
|
||||
// 回复200 OK
|
||||
responseAck(evt);
|
||||
if (rootElement.getName().equals("Response")) {// !XmlUtil.isEmpty(result)) {
|
||||
if (rootElement.getName().equals("Response")) {// !StringUtils.isEmpty(result)) {
|
||||
// 此处是对本平台发出DeviceControl指令的应答
|
||||
JSONObject json = new JSONObject();
|
||||
XmlUtil.node2Json(rootElement, json);
|
||||
@@ -718,7 +718,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
||||
deviceAlarm.setLatitude(0.00);
|
||||
}
|
||||
|
||||
if (!XmlUtil.isEmpty(deviceAlarm.getAlarmMethod())) {
|
||||
if (!StringUtils.isEmpty(deviceAlarm.getAlarmMethod())) {
|
||||
if ( deviceAlarm.getAlarmMethod().equals("4")) {
|
||||
MobilePosition mobilePosition = new MobilePosition();
|
||||
mobilePosition.setDeviceId(deviceAlarm.getDeviceId());
|
||||
|
||||
@@ -17,6 +17,7 @@ import org.dom4j.Element;
|
||||
import org.dom4j.io.SAXReader;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* 基于dom4j的工具包
|
||||
@@ -114,12 +115,12 @@ public class XmlUtil {
|
||||
// 如果是属性
|
||||
for (Object o : element.attributes()) {
|
||||
Attribute attr = (Attribute) o;
|
||||
if (!isEmpty(attr.getValue())) {
|
||||
if (!StringUtils.isEmpty(attr.getValue())) {
|
||||
json.put("@" + attr.getName(), attr.getValue());
|
||||
}
|
||||
}
|
||||
List<Element> chdEl = element.elements();
|
||||
if (chdEl.isEmpty() && !isEmpty(element.getText())) {// 如果没有子元素,只有一个值
|
||||
if (chdEl.isEmpty() && !StringUtils.isEmpty(element.getText())) {// 如果没有子元素,只有一个值
|
||||
json.put(element.getName(), element.getText());
|
||||
}
|
||||
|
||||
@@ -150,7 +151,7 @@ public class XmlUtil {
|
||||
} else { // 子元素没有子元素
|
||||
for (Object o : element.attributes()) {
|
||||
Attribute attr = (Attribute) o;
|
||||
if (!isEmpty(attr.getValue())) {
|
||||
if (!StringUtils.isEmpty(attr.getValue())) {
|
||||
json.put("@" + attr.getName(), attr.getValue());
|
||||
}
|
||||
}
|
||||
@@ -160,11 +161,4 @@ public class XmlUtil {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isEmpty(String str) {
|
||||
if (str == null || str.trim().isEmpty() || "null".equals(str)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user