From c1b3f2beb4b76e89d4938d2f7d5b31ff0f10220d Mon Sep 17 00:00:00 2001 From: panlinlin <648540858@qq.com> Date: Sun, 24 Jan 2021 20:46:06 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9B=BD=E6=A0=87=E7=BA=A7=E8=81=94--=E7=82=B9?= =?UTF-8?q?=E6=92=AD-=E6=9C=AA=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gb28181/transmit/SIPProcessorFactory.java | 5 + .../request/impl/InviteRequestProcessor.java | 175 ++++++++++++------ .../storager/dao/PatformChannelMapper.java | 4 + .../impl/VideoManagerStoragerImpl.java | 3 +- web_src/.postcssrc.js | 2 +- 5 files changed, 128 insertions(+), 61 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java index f4e49281..d48cae56 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java @@ -10,6 +10,7 @@ import javax.sip.message.Request; 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.storager.IRedisCatchStorage; import com.alibaba.fastjson.JSON; import com.genersoft.iot.vmp.gb28181.transmit.response.impl.*; @@ -107,6 +108,9 @@ public class SIPProcessorFactory { @Autowired private IPlayService playService; + @Autowired + private ZLMRTPServerFactory zlmrtpServerFactory; + // 注:这里使用注解会导致循环依赖注入,暂用springBean private SipProvider tcpSipProvider; @@ -128,6 +132,7 @@ public class SIPProcessorFactory { processor.setCmderFroPlatform(cmderFroPlatform); processor.setPlayService(playService); processor.setStorager(storager); + processor.setZlmrtpServerFactory(zlmrtpServerFactory); return processor; } else if (Request.REGISTER.equals(method)) { RegisterRequestProcessor processor = new RegisterRequestProcessor(); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java index 58e11ad6..9d0a9a3f 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java @@ -1,5 +1,6 @@ package com.genersoft.iot.vmp.gb28181.transmit.request.impl; +import javax.sdp.*; import javax.sip.InvalidArgumentException; import javax.sip.RequestEvent; import javax.sip.SipException; @@ -11,20 +12,18 @@ import javax.sip.message.Request; import javax.sip.message.Response; import com.alibaba.fastjson.JSONObject; +import com.genersoft.iot.vmp.conf.MediaServerConfig; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; -import com.genersoft.iot.vmp.gb28181.sdp.Codec; -import com.genersoft.iot.vmp.gb28181.sdp.MediaDescription; -import com.genersoft.iot.vmp.gb28181.sdp.SdpParser; -import com.genersoft.iot.vmp.gb28181.sdp.SessionDescription; -import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; -import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; 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.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import com.genersoft.iot.vmp.vmanager.play.bean.PlayResult; import com.genersoft.iot.vmp.vmanager.service.IPlayService; +import gov.nist.javax.sdp.fields.SDPFormat; import gov.nist.javax.sip.address.AddressImpl; import gov.nist.javax.sip.address.SipUri; import org.slf4j.Logger; @@ -34,6 +33,8 @@ import org.springframework.beans.factory.annotation.Autowired; import java.io.IOException; import java.text.ParseException; import java.util.List; +import java.util.UUID; +import java.util.Vector; /** * @Description:处理INVITE请求 @@ -48,10 +49,22 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor { private IVideoManagerStorager storager; + private IRedisCatchStorage redisCatchStorage; + private SIPCommander cmder; private IPlayService playService; + private ZLMRTPServerFactory zlmrtpServerFactory; + + public ZLMRTPServerFactory getZlmrtpServerFactory() { + return zlmrtpServerFactory; + } + + public void setZlmrtpServerFactory(ZLMRTPServerFactory zlmrtpServerFactory) { + this.zlmrtpServerFactory = zlmrtpServerFactory; + } + /** * 处理invite请求 * @@ -98,64 +111,105 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor { }else { response100Ack(evt); // 通道存在,发100,trying } - // 解析sdp消息 - SessionDescription sdp = new SdpParser().parse(request.getRawContent()); + // 解析sdp消息, 使用jainsip 自带的sdp解析方式 + String contentString = new String(request.getRawContent()); + SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(contentString); + + // TODO 区分TCP发流还是udp, 当前默认udp // 获取支持的格式 - List mediaDescriptions = sdp.getMediaDescriptions(); + Vector mediaDescriptions = sdp.getMediaDescriptions(true); // 查看是否支持PS 负载96 String ip = null; int port = -1; - for (MediaDescription mediaDescription : mediaDescriptions) { - - List codecs = mediaDescription.getCodecs(); - for (Codec codec : codecs) { - if("96".equals(codec.getPayloadType()) || "PS".equals(codec.getName()) || "ps".equals(codec.getName())) { - ip = mediaDescription.getIpAddress().getHostName(); - port = mediaDescription.getPort(); - break; - } - } - } - if (ip == null || port == -1) { // TODO 没有合适的视频流格式, 可配置是否使用第一个media信息 - if (mediaDescriptions.size() > 0) { - ip = mediaDescriptions.get(0).getIpAddress().getHostName(); - port = mediaDescriptions.get(0).getPort(); - } + for (int i = 0; i < mediaDescriptions.size(); i++) { + MediaDescription mediaDescription = (MediaDescription)mediaDescriptions.get(i); + Media media = mediaDescription.getMedia(); + port = media.getMediaPort(); } - - if (ip == null || port == -1) { - response488Ack(evt); - return; - } - - - String ssrc = sdp.getSsrc(); - - Device device = storager.queryVideoDeviceByPlatformIdAndChannelId(platformId, channelId); - if (device == null) { - logger.warn("点播平台{}的通道{}时未找到设备信息", platformId, channel); - response500Ack(evt); - return; - } - - // 通知下级推流, - PlayResult playResult = playService.play(device.getDeviceId(), channelId, (response)->{ - // 收到推流, 回复200OK - - },(event -> { - // 未知错误。直接转发设备点播的错误 - Response response = null; - try { - response = getMessageFactory().createResponse(event.getResponse().getStatusCode(), evt.getRequest()); - getServerTransaction(evt).sendResponse(response); - - } catch (ParseException | SipException | InvalidArgumentException e) { - e.printStackTrace(); - } - })); - playResult.getResult(); +// for (MediaDescription mediaDescription : mediaDescriptions) { +// +// List codecs = mediaDescription.getCodecs(); +// for (Codec codec : codecs) { +// if("96".equals(codec.getPayloadType()) || "PS".equals(codec.getName()) || "ps".equals(codec.getName())) { +// // TODO 这里很慢 +// ip = mediaDescription.getIpAddress().getHostName(); +// port = mediaDescription.getPort(); +// break; +// } +// } +// } +// if (ip == null || port == -1) { // TODO 没有合适的视频流格式, 可配置是否使用第一个media信息 +// if (mediaDescriptions.size() > 0) { +// ip = mediaDescriptions.get(0).getIpAddress().getHostName(); +// port = mediaDescriptions.get(0).getPort(); +// } +// } +// +// if (ip == null || port == -1) { +// response488Ack(evt); +// return; +// } +// +// +// String ssrc = sdp.getSsrc(); +// +// Device device = storager.queryVideoDeviceByPlatformIdAndChannelId(platformId, channelId); +// if (device == null) { +// logger.warn("点播平台{}的通道{}时未找到设备信息", platformId, channel); +// response500Ack(evt); +// return; +// } +// +// // 通知下级推流, +// PlayResult playResult = playService.play(device.getDeviceId(), channelId, (responseJSON)->{ +// // 收到推流, 回复200OK +// UUID uuid = UUID.randomUUID(); +// int rtpServer = zlmrtpServerFactory.createRTPServer(uuid.toString()); +// if (rtpServer == -1) { +// logger.error("为获取到可用端口"); +// return; +// }else { +// zlmrtpServerFactory.closeRTPServer(uuid.toString()); +// } +// // TODO 添加对tcp的支持 +// MediaServerConfig mediaInfo = redisCatchStorage.getMediaInfo(); +// StringBuffer content = new StringBuffer(200); +// content.append("v=0\r\n"); +// content.append("o="+"00000"+" 0 0 IN IP4 "+mediaInfo.getWanIp()+"\r\n"); +// content.append("s=Play\r\n"); +// content.append("c=IN IP4 "+mediaInfo.getWanIp()+"\r\n"); +// content.append("t=0 0\r\n"); +// content.append("m=video "+ rtpServer+" RTP/AVP 96\r\n"); +// content.append("a=sendonly\r\n"); +// content.append("a=rtpmap:96 PS/90000\r\n"); +// content.append("y="+ ssrc + "\r\n"); +// content.append("f=\r\n"); +// +// try { +// responseAck(evt, content.toString()); +// } catch (SipException e) { +// e.printStackTrace(); +// } catch (InvalidArgumentException e) { +// e.printStackTrace(); +// } catch (ParseException e) { +// e.printStackTrace(); +// } +// +// // 写入redis, 超时时回复 +//// redisCatchStorage.waiteAck() +// },(event -> { +// // 未知错误。直接转发设备点播的错误 +// Response response = null; +// try { +// response = getMessageFactory().createResponse(event.getResponse().getStatusCode(), evt.getRequest()); +// getServerTransaction(evt).sendResponse(response); +// +// } catch (ParseException | SipException | InvalidArgumentException e) { +// e.printStackTrace(); +// } +// })); +// playResult.getResult(); // 查找合适的端口推流, - // 发送 200ok // 收到ack后调用推流接口 @@ -163,9 +217,12 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor { } catch (SipException | InvalidArgumentException | ParseException e) { e.printStackTrace(); - } catch (IOException e) { logger.warn("sdp解析错误"); e.printStackTrace(); + } catch (SdpParseException e) { + e.printStackTrace(); + } catch (SdpException e) { + e.printStackTrace(); } } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/PatformChannelMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/PatformChannelMapper.java index a5ee2755..50eb3e3d 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/PatformChannelMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/PatformChannelMapper.java @@ -1,5 +1,6 @@ package com.genersoft.iot.vmp.storager.dao; +import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.vmanager.platform.bean.ChannelReduce; import org.apache.ibatis.annotations.Delete; @@ -45,4 +46,7 @@ public interface PatformChannelMapper { @Select("SELECT * FROM device_channel WHERE deviceId = (SELECT deviceId FROM platform_gb_channel WHERE " + "platformId='${platformId}' AND channelId='${channelId}' ) AND channelId='${channelId}'") DeviceChannel queryChannelInParentPlatform(String platformId, String channelId); + + @Select("SELECT * FROM device WHERE deviceId = (SELECT deviceId FROM platform_gb_channel WHERE platformId='${platformId}' AND channelId='${channelId}')") + Device queryVideoDeviceByPlatformIdAndChannelId(String platformId, String channelId); } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java index dac0aa24..7417935b 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java @@ -338,6 +338,7 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { @Override public Device queryVideoDeviceByPlatformIdAndChannelId(String platformId, String channelId) { - return null; + Device device = patformChannelMapper.queryVideoDeviceByPlatformIdAndChannelId(platformId, channelId); + return device; } } diff --git a/web_src/.postcssrc.js b/web_src/.postcssrc.js index 406b4d24..f98d56a5 100644 --- a/web_src/.postcssrc.js +++ b/web_src/.postcssrc.js @@ -7,7 +7,7 @@ module.exports = { // to edit target browsers: use "browserslist" field in package.json "autoprefixer": {}, 'postcss-pxtorem': { - rootValue: 24, + rootValue: 16, propList: ['font-size'] // 只转化font-size } }