| | |
| | | package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
|
| | |
|
| | | import java.text.ParseException;
|
| | | import java.util.regex.Matcher;
|
| | | import java.util.regex.Pattern;
|
| | |
|
| | | import javax.sip.*;
|
| | | import javax.sip.address.SipURI;
|
| | |
| | | import javax.sip.header.ViaHeader;
|
| | | import javax.sip.message.Request;
|
| | |
|
| | | import com.alibaba.fastjson.JSONArray;
|
| | | import com.alibaba.fastjson.JSONObject;
|
| | | import com.genersoft.iot.vmp.common.StreamInfo;
|
| | | import com.genersoft.iot.vmp.conf.MediaServerConfig;
|
| | | import com.genersoft.iot.vmp.conf.MediaConfig;
|
| | | import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
|
| | | 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.storager.IRedisCatchStorage;
|
| | | import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
| | | import gov.nist.javax.sip.message.SIPRequest;
|
| | | import org.slf4j.Logger;
|
| | | import org.slf4j.LoggerFactory;
|
| | | import org.springframework.beans.factory.annotation.Autowired;
|
| | |
| | | @Autowired
|
| | | private ZLMRTPServerFactory zlmrtpServerFactory;
|
| | |
|
| | | @Value("${media.rtp.enable}")
|
| | | private boolean rtpEnable;
|
| | | @Autowired
|
| | | private ZLMRESTfulUtils zlmresTfulUtils;
|
| | |
|
| | | @Value("${media.seniorSdp}")
|
| | | @Autowired
|
| | | private MediaConfig mediaConfig;
|
| | |
|
| | | @Value("${userSettings.seniorSdp}")
|
| | | private boolean seniorSdp;
|
| | |
|
| | | @Value("${media.autoApplyPlay}")
|
| | | @Value("${userSettings.autoApplyPlay}")
|
| | | private boolean autoApplyPlay;
|
| | |
|
| | | @Value("${userSettings.waitTrack}")
|
| | | private boolean waitTrack;
|
| | |
|
| | | @Autowired
|
| | | private ZLMHttpHookSubscribe subscribe;
|
| | |
| | | public boolean frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2) {
|
| | | try {
|
| | | String cmdStr= frontEndCmdString(cmdCode, parameter1, parameter2, combineCode2);
|
| | | System.out.println("控制字符串:" + cmdStr);
|
| | | logger.info("控制字符串:" + cmdStr);
|
| | | StringBuffer ptzXml = new StringBuffer(200);
|
| | | ptzXml.append("<?xml version=\"1.0\" ?>\r\n");
|
| | | ptzXml.append("<Control>\r\n");
|
| | |
| | |
|
| | | /**
|
| | | * 请求预览视频流
|
| | | * @param device 视频设备
|
| | | * @param channelId 预览通道
|
| | | * @param event hook订阅
|
| | | * @param errorEvent sip错误订阅
|
| | | */
|
| | | * @param device 视频设备
|
| | | * @param channelId 预览通道
|
| | | * @param event hook订阅
|
| | | * @param errorEvent sip错误订阅
|
| | | */
|
| | | @Override
|
| | | public void playStreamCmd(Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent) {
|
| | | String streamId = null;
|
| | | try {
|
| | | if (device == null) return;
|
| | | String ssrc = streamSession.createPlaySsrc();
|
| | | String streamId = null;
|
| | | if (rtpEnable) {
|
| | | if (mediaConfig.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();
|
| | | MediaServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
|
| | | ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
|
| | | if (mediaInfo == null) {
|
| | | logger.warn("点播时发现ZLM尚未连接...");
|
| | | return;
|
| | | }
|
| | | String mediaPort = null;
|
| | | // 使用动态udp端口
|
| | | if (rtpEnable) {
|
| | | if (mediaConfig.isRtpEnable()) {
|
| | | mediaPort = zlmrtpServerFactory.createRTPServer(streamId) + "";
|
| | | }else {
|
| | | mediaPort = mediaInfo.getRtpProxyPort();
|
| | |
| | | subscribeKey.put("regist", true);
|
| | |
|
| | | subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, json->{
|
| | | if (json.getJSONArray("tracks") == null) return;
|
| | | if (waitTrack && json.getJSONArray("tracks") == null) return;
|
| | | event.response(json);
|
| | | subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
|
| | | });
|
| | | //
|
| | | StringBuffer content = new StringBuffer(200);
|
| | | content.append("v=0\r\n");
|
| | | // content.append("o="+channelId+" 0 0 IN IP4 "+mediaInfo.getWanIp()+"\r\n");
|
| | | // content.append("o=" + sipConfig.getSipId() + " 0 0 IN IP4 "+mediaInfo.getWanIp()+"\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("a=rtpmap:96 PS/90000\r\n");
|
| | | content.append("a=rtpmap:98 H264/90000\r\n");
|
| | | content.append("a=rtpmap:97 MPEG4/90000\r\n");
|
| | | if("TCP-PASSIVE".equals(streamMode)) { // tcp被动模式
|
| | | if ("TCP-PASSIVE".equals(streamMode)) { // tcp被动模式
|
| | | content.append("a=setup:passive\r\n");
|
| | | content.append("a=recvonly\r\n");
|
| | | content.append("a=rtpmap:96 PS/90000\r\n");
|
| | | content.append("a=rtpmap:98 H264/90000\r\n");
|
| | | content.append("a=rtpmap:97 MPEG4/90000\r\n");
|
| | | if ("TCP-PASSIVE".equals(streamMode)) { // tcp被动模式
|
| | | content.append("a=setup:passive\r\n");
|
| | | content.append("a=connection:new\r\n");
|
| | | } else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式
|
| | | content.append("a=setup:active\r\n");
|
| | | content.append("a=connection:new\r\n");
|
| | | }
|
| | | content.append("a=connection:new\r\n");
|
| | | } else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式
|
| | | content.append("a=setup:active\r\n");
|
| | | content.append("a=connection:new\r\n");
|
| | | }
|
| | | }
|
| | |
|
| | |
| | |
|
| | | Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, "FromInvt" + tm, null, ssrc, callIdHeader);
|
| | |
|
| | | ClientTransaction transaction = transmitRequest(device, request, errorEvent);
|
| | | streamSession.put(streamId,ssrc, transaction);
|
| | |
|
| | | ClientTransaction transaction = transmitRequest(device, request, (e -> {
|
| | | streamSession.remove(device.getDeviceId(), channelId);
|
| | | errorEvent.response(e);
|
| | | }));
|
| | | streamSession.put(device.getDeviceId(), channelId ,ssrc,streamId, transaction);
|
| | | |
| | | } catch ( SipException | ParseException | InvalidArgumentException e) {
|
| | | e.printStackTrace();
|
| | | }
|
| | |
| | | public void playbackStreamCmd(Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event
|
| | | , SipSubscribe.Event errorEvent) {
|
| | | try {
|
| | | MediaServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
|
| | | ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
|
| | | String ssrc = streamSession.createPlayBackSsrc();
|
| | | String streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
|
| | | // 添加订阅
|
| | |
| | | +DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) +"\r\n");
|
| | | String mediaPort = null;
|
| | | // 使用动态udp端口
|
| | | if (rtpEnable) {
|
| | | if (mediaConfig.isRtpEnable()) {
|
| | | mediaPort = zlmrtpServerFactory.createRTPServer(streamId) + "";
|
| | | }else {
|
| | | mediaPort = mediaInfo.getRtpProxyPort();
|
| | |
| | | Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader);
|
| | |
|
| | | ClientTransaction transaction = transmitRequest(device, request, errorEvent);
|
| | | streamSession.put(streamId, ssrc, transaction);
|
| | | streamSession.put(device.getDeviceId(), channelId, ssrc, streamId, transaction);
|
| | |
|
| | | } catch ( SipException | ParseException | InvalidArgumentException e) {
|
| | | e.printStackTrace();
|
| | |
| | | *
|
| | | */
|
| | | @Override
|
| | | public void streamByeCmd(String ssrc) {
|
| | | streamByeCmd(ssrc, null);
|
| | | public void streamByeCmd(String deviceId, String channelId) {
|
| | | streamByeCmd(deviceId, channelId, null);
|
| | | }
|
| | | @Override
|
| | | public void streamByeCmd(String streamId, SipSubscribe.Event okEvent) {
|
| | | public void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent) {
|
| | |
|
| | | try {
|
| | | ClientTransaction transaction = streamSession.get(streamId);
|
| | | // 服务重启后
|
| | | ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId);
|
| | | // 服务重启后, 无法直接发送bye, 通过手动构建发送
|
| | | if (transaction == null) {
|
| | | StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId);
|
| | | if (streamInfo != 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);
|
| | | }
|
| | | return;
|
| | | }
|
| | |
| | | }
|
| | | Request byeRequest = dialog.createRequest(Request.BYE);
|
| | | SipURI byeURI = (SipURI) byeRequest.getRequestURI();
|
| | | String vh = transaction.getRequest().getHeader(ViaHeader.NAME).toString();
|
| | | Pattern p = Pattern.compile("(\\d+\\.\\d+\\.\\d+\\.\\d+)\\:(\\d+)");
|
| | | Matcher matcher = p.matcher(vh);
|
| | | if (matcher.find()) {
|
| | | String ip = matcher.group(1);
|
| | | byeURI.setHost(ip);
|
| | | String port = matcher.group(2);
|
| | | byeURI.setPort(Integer.parseInt(port));
|
| | | }
|
| | | SIPRequest request = (SIPRequest)transaction.getRequest();
|
| | | byeURI.setHost(request.getRemoteAddress().getHostName());
|
| | | byeURI.setPort(request.getRemotePort());
|
| | | ViaHeader viaHeader = (ViaHeader) byeRequest.getHeader(ViaHeader.NAME);
|
| | | String protocol = viaHeader.getTransport().toUpperCase();
|
| | | ClientTransaction clientTransaction = null;
|
| | |
| | | }
|
| | |
|
| | | dialog.sendRequest(clientTransaction);
|
| | |
|
| | | streamSession.remove(streamId);
|
| | | zlmrtpServerFactory.closeRTPServer(streamId);
|
| | | } catch (TransactionDoesNotExistException e) {
|
| | | e.printStackTrace();
|
| | | } catch (SipException e) {
|
| | | e.printStackTrace();
|
| | | } catch (ParseException e) {
|
| | | zlmrtpServerFactory.closeRTPServer(streamSession.getStreamId(deviceId, channelId));
|
| | | streamSession.remove(deviceId, channelId);
|
| | | } catch (SipException | ParseException e) {
|
| | | e.printStackTrace();
|
| | | }
|
| | | }
|
| | |
| | | * 语音广播
|
| | | *
|
| | | * @param device 视频设备
|
| | | * @param channelId 预览通道
|
| | | */
|
| | | @Override
|
| | | public boolean audioBroadcastCmd(Device device) {
|
| | |
| | | * @param device 视频设备
|
| | | * @param startPriority 报警起始级别(可选)
|
| | | * @param endPriority 报警终止级别(可选)
|
| | | * @param alarmMethods 报警方式条件(可选)
|
| | | * @param alarmMethod 报警方式条件(可选)
|
| | | * @param alarmType 报警类型
|
| | | * @param startTime 报警发生起始时间(可选)
|
| | | * @param endTime 报警发生终止时间(可选)
|
| | |
| | |
|
| | | @Override
|
| | | public void closeRTPServer(Device device, String channelId) {
|
| | | if (rtpEnable) {
|
| | | if (mediaConfig.isRtpEnable()) {
|
| | | String streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
|
| | | zlmrtpServerFactory.closeRTPServer(streamId);
|
| | | }
|
| | | streamSession.remove(device.getDeviceId(), channelId);
|
| | | }
|
| | | }
|