| | |
| | | import javax.sip.header.ViaHeader;
|
| | | import javax.sip.message.Request;
|
| | |
|
| | | import com.alibaba.fastjson.JSON;
|
| | | 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.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;
|
| | |
|
| | | @Autowired
|
| | | private ZLMRESTfulUtils zlmresTfulUtils;
|
| | |
|
| | | @Value("${media.rtp.enable}")
|
| | | private boolean rtpEnable;
|
| | |
| | |
|
| | | /**
|
| | | * 请求预览视频流
|
| | | * @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) {
|
| | | streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
|
| | | }else {
|
| | |
| | | //
|
| | | 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");
|
| | |
| | |
|
| | | 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();
|
| | | }
|
| | |
| | | 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 报警发生终止时间(可选)
|
| | |
| | | String streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
|
| | | zlmrtpServerFactory.closeRTPServer(streamId);
|
| | | }
|
| | | streamSession.remove(device.getDeviceId(), channelId);
|
| | | }
|
| | | }
|