| | |
| | | public class StreamInfo { |
| | | |
| | | private String app; |
| | | private String streamId; |
| | | private String stream; |
| | | private String deviceID; |
| | | private String channelId; |
| | | private String flv; |
| | |
| | | this.ws_ts = ws_ts; |
| | | } |
| | | |
| | | public String getStreamId() { |
| | | return streamId; |
| | | public String getStream() { |
| | | return stream; |
| | | } |
| | | |
| | | public void setStreamId(String streamId) { |
| | | this.streamId = streamId; |
| | | public void setStream(String stream) { |
| | | this.stream = stream; |
| | | } |
| | | |
| | | public String getRtc() { |
| | |
| | | // 此处多了一个_,暂不修改
|
| | | public static final String PLAYER_PREFIX = "VMP_PLAYER_";
|
| | | public static final String PLAY_BLACK_PREFIX = "VMP_PLAYBACK_";
|
| | | public static final String PLAY_INFO_PREFIX = "VMP_PLAY_INFO_";
|
| | |
|
| | | public static final String DOWNLOAD_PREFIX = "VMP_DOWNLOAD_";
|
| | |
|
| | |
| | | |
| | | private String deviceId; |
| | | private String channelId; |
| | | private String ssrc; |
| | | private String streamId; |
| | | private String callId; |
| | | private String stream; |
| | | private byte[] transaction; |
| | | private byte[] dialog; |
| | | private String mediaServerId; |
| | | private String ssrc; |
| | | |
| | | public String getDeviceId() { |
| | | return deviceId; |
| | |
| | | this.channelId = channelId; |
| | | } |
| | | |
| | | public String getSsrc() { |
| | | return ssrc; |
| | | public String getCallId() { |
| | | return callId; |
| | | } |
| | | |
| | | public void setSsrc(String ssrc) { |
| | | this.ssrc = ssrc; |
| | | public void setCallId(String callId) { |
| | | this.callId = callId; |
| | | } |
| | | |
| | | public String getStreamId() { |
| | | return streamId; |
| | | public String getStream() { |
| | | return stream; |
| | | } |
| | | |
| | | public void setStreamId(String streamId) { |
| | | this.streamId = streamId; |
| | | public void setStream(String stream) { |
| | | this.stream = stream; |
| | | } |
| | | |
| | | public byte[] getTransaction() { |
| | |
| | | public void setMediaServerId(String mediaServerId) { |
| | | this.mediaServerId = mediaServerId; |
| | | } |
| | | |
| | | public String getSsrc() { |
| | | return ssrc; |
| | | } |
| | | |
| | | public void setSsrc(String ssrc) { |
| | | this.ssrc = ssrc; |
| | | } |
| | | } |
| | |
| | | import gov.nist.javax.sip.stack.SIPDialog;
|
| | | import org.springframework.beans.factory.annotation.Autowired;
|
| | | import org.springframework.stereotype.Component;
|
| | | import org.springframework.util.StringUtils;
|
| | |
|
| | | /**
|
| | | * @description:视频流session管理器,管理视频预览、预览回放的通信句柄
|
| | |
| | | @Autowired
|
| | | private UserSetup userSetup;
|
| | |
|
| | | public void put(String deviceId, String channelId ,String ssrc, String streamId, String mediaServerId, ClientTransaction transaction){
|
| | | /**
|
| | | * 添加一个点播/回放的事务信息
|
| | | * 后续可以通过流Id/callID
|
| | | * @param deviceId 设备ID
|
| | | * @param channelId 通道ID
|
| | | * @param callId 一次请求的CallID
|
| | | * @param stream 流名称
|
| | | * @param mediaServerId 所使用的流媒体ID
|
| | | * @param transaction 事务
|
| | | */
|
| | | public void put(String deviceId, String channelId, String callId, String stream, String ssrc, String mediaServerId, ClientTransaction transaction){
|
| | | SsrcTransaction ssrcTransaction = new SsrcTransaction();
|
| | | ssrcTransaction.setDeviceId(deviceId);
|
| | | ssrcTransaction.setChannelId(channelId);
|
| | | ssrcTransaction.setStreamId(streamId);
|
| | | ssrcTransaction.setStream(stream);
|
| | | byte[] transactionByteArray = SerializeUtils.serialize(transaction);
|
| | | ssrcTransaction.setTransaction(transactionByteArray);
|
| | | ssrcTransaction.setCallId(callId);
|
| | | ssrcTransaction.setSsrc(ssrc);
|
| | | ssrcTransaction.setMediaServerId(mediaServerId);
|
| | |
|
| | | redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_" + deviceId + "_" + channelId, ssrcTransaction);
|
| | | redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId()
|
| | | + "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction);
|
| | | redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId()
|
| | | + "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction);
|
| | | }
|
| | |
|
| | | public void put(String deviceId, String channelId , Dialog dialog){
|
| | | SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
|
| | | public void put(String deviceId, String channelId, String callId, Dialog dialog){
|
| | | SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, callId, null);
|
| | | if (ssrcTransaction != null) {
|
| | | byte[] dialogByteArray = SerializeUtils.serialize(dialog);
|
| | | ssrcTransaction.setDialog(dialogByteArray);
|
| | | }
|
| | | redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_" + deviceId + "_" + channelId, ssrcTransaction);
|
| | | redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId()
|
| | | + "_" + deviceId + "_" + channelId + "_" + ssrcTransaction.getCallId() + "_"
|
| | | + ssrcTransaction.getStream(), ssrcTransaction);
|
| | | }
|
| | |
|
| | |
|
| | | public ClientTransaction getTransaction(String deviceId, String channelId){
|
| | | SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
|
| | | public ClientTransaction getTransactionByStream(String deviceId, String channelId, String stream){
|
| | | SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
|
| | | if (ssrcTransaction == null) return null;
|
| | | byte[] transactionByteArray = ssrcTransaction.getTransaction();
|
| | | ClientTransaction clientTransaction = (ClientTransaction)SerializeUtils.deSerialize(transactionByteArray);
|
| | | return clientTransaction;
|
| | | }
|
| | |
|
| | | public SIPDialog getDialog(String deviceId, String channelId){
|
| | | SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
|
| | | public SIPDialog getDialogByStream(String deviceId, String channelId, String stream){
|
| | | SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
|
| | | if (ssrcTransaction == null) return null;
|
| | | byte[] dialogByteArray = ssrcTransaction.getDialog();
|
| | | if (dialogByteArray == null) return null;
|
| | |
| | | return dialog;
|
| | | }
|
| | |
|
| | | public SsrcTransaction getSsrcTransaction(String deviceId, String channelId){
|
| | | SsrcTransaction ssrcTransaction = (SsrcTransaction)redisUtil.get(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_" + deviceId + "_" + channelId);
|
| | | return ssrcTransaction;
|
| | | public SsrcTransaction getSsrcTransaction(String deviceId, String channelId, String callId, String stream){
|
| | | if (StringUtils.isEmpty(callId)) callId ="*";
|
| | | if (StringUtils.isEmpty(stream)) stream ="*";
|
| | | String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_" + deviceId + "_" + channelId + "_" + callId+ "_" + stream;
|
| | | List<Object> scanResult = redisUtil.scan(key);
|
| | | if (scanResult.size() == 0) return null;
|
| | | return (SsrcTransaction)redisUtil.get((String) scanResult.get(0));
|
| | | }
|
| | |
|
| | | public String getStreamId(String deviceId, String channelId){
|
| | | SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
|
| | | if (ssrcTransaction == null) return null;
|
| | | return ssrcTransaction.getStreamId();
|
| | | }
|
| | | public String getMediaServerId(String deviceId, String channelId){
|
| | | SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
|
| | | public String getMediaServerId(String deviceId, String channelId, String stream){
|
| | | SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
|
| | | if (ssrcTransaction == null) return null;
|
| | | return ssrcTransaction.getMediaServerId();
|
| | | }
|
| | |
|
| | | public String getSSRC(String deviceId, String channelId){
|
| | | SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
|
| | | public String getSSRC(String deviceId, String channelId, String stream){
|
| | | SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
|
| | | if (ssrcTransaction == null) return null;
|
| | | return ssrcTransaction.getSsrc();
|
| | | }
|
| | |
|
| | | public void remove(String deviceId, String channelId) {
|
| | | SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
|
| | | public void remove(String deviceId, String channelId, String stream) {
|
| | | SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
|
| | | if (ssrcTransaction == null) return;
|
| | | redisUtil.del(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_" + deviceId + "_" + channelId);
|
| | | redisUtil.del(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_"
|
| | | + deviceId + "_" + channelId + "_" + ssrcTransaction.getCallId() + "_" + ssrcTransaction.getStream());
|
| | | }
|
| | |
|
| | |
|
| | | public List<SsrcTransaction> getAllSsrc() {
|
| | | List<Object> ssrcTransactionKeys = redisUtil.scan(String.format("%s_*_*", VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX+ userSetup.getServerId() + "_" ));
|
| | | List<Object> ssrcTransactionKeys = redisUtil.scan(String.format("%s_*_*_*_*", VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX+ userSetup.getServerId() + "_" ));
|
| | | List<SsrcTransaction> result= new ArrayList<>();
|
| | | for (int i = 0; i < ssrcTransactionKeys.size(); i++) {
|
| | | String key = (String)ssrcTransactionKeys.get(i);
|
| | |
| | | /**
|
| | | * 视频流停止
|
| | | */
|
| | | void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent);
|
| | | void streamByeCmd(String deviceId, String channelId);
|
| | | void streamByeCmd(String deviceId, String channelId, String ssrc, SipSubscribe.Event okEvent);
|
| | | void streamByeCmd(String deviceId, String channelId, String ssrc);
|
| | |
|
| | | /**
|
| | | * 回放暂停
|
| | |
| | | * @return |
| | | */ |
| | | boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent); |
| | | boolean register(ParentPlatform parentPlatform, String callId, WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent); |
| | | boolean register(ParentPlatform parentPlatform, String callId, WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain); |
| | | |
| | | /** |
| | | * 向上级平台注销 |
| | |
| | | |
| | | |
| | | Request registerRequest = createRegisterRequest(parentPlatform, redisCatchStorage.getCSEQ(Request.REGISTER), fromTag, viaTag, callIdHeader); |
| | | |
| | | SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort()); |
| | | if (www == null) { |
| | | AuthorizationHeader authorizationHeader = sipFactory.createHeaderFactory().createAuthorizationHeader("Digest"); |
| | | authorizationHeader.setUsername(parentPlatform.getDeviceGBId()); |
| | | authorizationHeader.setURI(requestURI); |
| | | authorizationHeader.setAlgorithm("MD5"); |
| | | registerRequest.addHeader(authorizationHeader); |
| | | return registerRequest; |
| | | } |
| | | String realm = www.getRealm(); |
| | | String nonce = www.getNonce(); |
| | | String scheme = www.getScheme(); |
| | |
| | | |
| | | callIdHeader.setCallId(callId); |
| | | |
| | | SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort()); |
| | | String cNonce = null; |
| | | String nc = "00000001"; |
| | | if (qop != null) { |
| | |
| | | throws PeerUnavailableException, ParseException, InvalidArgumentException {
|
| | | Request request = null;
|
| | | if (streamInfo == null) return null;
|
| | | Dialog dialog = streamSession.getDialog(streamInfo.getDeviceID(), streamInfo.getChannelId());
|
| | | Dialog dialog = streamSession.getDialogByStream(streamInfo.getDeviceID(), streamInfo.getChannelId(), streamInfo.getStream());
|
| | |
|
| | | SipURI requestLine = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(),
|
| | | device.getHostAddress());
|
| | |
| | | */
|
| | | @Override
|
| | | public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent) {
|
| | | String streamId = ssrcInfo.getStreamId();
|
| | | String streamId = ssrcInfo.getStream();
|
| | | try {
|
| | | if (device == null) return;
|
| | | String streamMode = device.getStreamMode().toUpperCase();
|
| | |
| | | }
|
| | |
|
| | | content.append("y="+ssrcInfo.getSsrc()+"\r\n");//ssrc
|
| | | // f字段:f= v/编码格式/分辨率/帧率/码率类型/码率大小a/编码格式/码率大小/采样率
|
| | | // content.append("f=v/2/5/25/1/4000a/1/8/1" + "\r\n"); // 未发现支持此特性的设备
|
| | |
|
| | | String tm = Long.toString(System.currentTimeMillis());
|
| | |
|
| | |
| | |
|
| | | Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, "FromInvt" + tm, null, ssrcInfo.getSsrc(), callIdHeader);
|
| | |
|
| | | String finalStreamId = streamId;
|
| | | transmitRequest(device, request, (e -> {
|
| | | streamSession.remove(device.getDeviceId(), channelId);
|
| | | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
|
| | | mediaServerService.releaseSsrc(mediaServerItem, ssrcInfo.getSsrc());
|
| | | errorEvent.response(e);
|
| | | }), e ->{
|
| | | streamSession.put(device.getDeviceId(), channelId ,ssrcInfo.getSsrc(), finalStreamId, mediaServerItem.getId(), ((ResponseEvent)e.event).getClientTransaction());
|
| | | streamSession.put(device.getDeviceId(), channelId , e.dialog);
|
| | | // 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值
|
| | | streamSession.put(device.getDeviceId(), channelId ,"play", streamId, ssrcInfo.getSsrc(), mediaServerItem.getId(), ((ResponseEvent)e.event).getClientTransaction());
|
| | | streamSession.put(device.getDeviceId(), channelId ,"play", e.dialog);
|
| | | });
|
| | |
|
| | |
|
| | |
| | | , SipSubscribe.Event errorEvent) {
|
| | | try {
|
| | |
|
| | | logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStreamId(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
|
| | | logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
|
| | |
|
| | | // 添加订阅
|
| | | JSONObject subscribeKey = new JSONObject();
|
| | | subscribeKey.put("app", "rtp");
|
| | | subscribeKey.put("stream", ssrcInfo.getStreamId());
|
| | | subscribeKey.put("stream", ssrcInfo.getStream());
|
| | | subscribeKey.put("regist", true);
|
| | | subscribeKey.put("mediaServerId", mediaServerItem.getId());
|
| | | logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString());
|
| | |
| | | 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");
|
| | |
|
| | |
|
| | |
|
| | | String streamMode = device.getStreamMode().toUpperCase();
|
| | |
|
| | |
| | |
|
| | | transmitRequest(device, request, errorEvent, okEvent -> {
|
| | | ResponseEvent responseEvent = (ResponseEvent) okEvent.event;
|
| | | streamSession.put(device.getDeviceId(), channelId, ssrcInfo.getSsrc(), ssrcInfo.getStreamId(), mediaServerItem.getId(), responseEvent.getClientTransaction());
|
| | | streamSession.put(device.getDeviceId(), channelId, okEvent.dialog);
|
| | | streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), responseEvent.getClientTransaction());
|
| | | streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), okEvent.dialog);
|
| | | });
|
| | | } catch ( SipException | ParseException | InvalidArgumentException e) {
|
| | | e.printStackTrace();
|
| | |
| | | public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, String startTime, String endTime, String downloadSpeed, ZLMHttpHookSubscribe.Event event
|
| | | , SipSubscribe.Event errorEvent) {
|
| | | try {
|
| | | logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStreamId(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
|
| | | logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
|
| | |
|
| | | // 添加订阅
|
| | | JSONObject subscribeKey = new JSONObject();
|
| | | subscribeKey.put("app", "rtp");
|
| | | subscribeKey.put("stream", ssrcInfo.getStreamId());
|
| | | subscribeKey.put("stream", ssrcInfo.getStream());
|
| | | subscribeKey.put("regist", true);
|
| | | subscribeKey.put("mediaServerId", mediaServerItem.getId());
|
| | | logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString());
|
| | |
| | | Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader, ssrcInfo.getSsrc());
|
| | |
|
| | | ClientTransaction transaction = transmitRequest(device, request, errorEvent);
|
| | | streamSession.put(device.getDeviceId(), channelId, ssrcInfo.getSsrc(), ssrcInfo.getStreamId(), mediaServerItem.getId(), transaction);
|
| | | streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), transaction);
|
| | | streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), transaction);
|
| | |
|
| | | } catch ( SipException | ParseException | InvalidArgumentException e) {
|
| | | e.printStackTrace();
|
| | |
| | | * 视频流停止, 不使用回调
|
| | | */
|
| | | @Override
|
| | | public void streamByeCmd(String deviceId, String channelId) {
|
| | | streamByeCmd(deviceId, channelId, null);
|
| | | public void streamByeCmd(String deviceId, String channelId, String stream) {
|
| | | streamByeCmd(deviceId, channelId, stream, null);
|
| | | }
|
| | |
|
| | | /**
|
| | | * 视频流停止
|
| | | */
|
| | | @Override
|
| | | public void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent) {
|
| | | public void streamByeCmd(String deviceId, String channelId, String stream, SipSubscribe.Event okEvent) {
|
| | | try {
|
| | | ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId);
|
| | | ClientTransaction transaction = streamSession.getTransactionByStream(deviceId, channelId, stream);
|
| | | if (transaction == null) {
|
| | | logger.warn("[ {} -> {}]停止视频流的时候发现事务已丢失", deviceId, channelId);
|
| | | SipSubscribe.EventResult<Object> eventResult = new SipSubscribe.EventResult<>();
|
| | |
| | | }
|
| | | return;
|
| | | }
|
| | | SIPDialog dialog = streamSession.getDialog(deviceId, channelId);
|
| | | SIPDialog dialog = streamSession.getDialogByStream(deviceId, channelId, stream);
|
| | | if (dialog == null) {
|
| | | logger.warn("[ {} -> {}]停止视频流的时候发现对话已丢失", deviceId, channelId);
|
| | | return;
|
| | |
| | |
|
| | | dialog.sendRequest(clientTransaction);
|
| | |
|
| | | SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(deviceId, channelId);
|
| | | SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(deviceId, channelId, callIdHeader.getCallId(), null);
|
| | | if (ssrcTransaction != null) {
|
| | | MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransaction.getMediaServerId());
|
| | | mediaServerService.releaseSsrc(mediaServerItem, ssrcTransaction.getSsrc());
|
| | | streamSession.remove(deviceId, channelId);
|
| | | streamSession.remove(deviceId, channelId, ssrcTransaction.getStream());
|
| | | }
|
| | | } catch (SipException | ParseException e) {
|
| | | e.printStackTrace();
|
| | |
| | | |
| | | @Override |
| | | public boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) { |
| | | return register(parentPlatform, null, null, errorEvent, okEvent); |
| | | return register(parentPlatform, null, null, errorEvent, okEvent, false); |
| | | } |
| | | |
| | | @Override |
| | |
| | | redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); |
| | | } |
| | | |
| | | return register(parentPlatform, null, null, errorEvent, okEvent); |
| | | return register(parentPlatform, null, null, errorEvent, okEvent, false); |
| | | } |
| | | |
| | | @Override |
| | | public boolean register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) { |
| | | public boolean register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable WWWAuthenticateHeader www, |
| | | SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain) { |
| | | try { |
| | | Request request = null; |
| | | String tm = Long.toString(System.currentTimeMillis()); |
| | | if (www == null ) { |
| | | if (!registerAgain ) { |
| | | // //callid |
| | | CallIdHeader callIdHeader = null; |
| | | if(parentPlatform.getTransport().equals("TCP")) { |
| | |
| | | if (deviceId == null) { |
| | | streamInfo = new StreamInfo(); |
| | | streamInfo.setApp(sendRtpItem.getApp()); |
| | | streamInfo.setStreamId(sendRtpItem.getStreamId()); |
| | | streamInfo.setStream(sendRtpItem.getStreamId()); |
| | | }else { |
| | | streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); |
| | | sendRtpItem.setStreamId(streamInfo.getStreamId()); |
| | | sendRtpItem.setStreamId(streamInfo.getStream()); |
| | | streamInfo.setApp("rtp"); |
| | | } |
| | | |
| | |
| | | Map<String, Object> param = new HashMap<>(); |
| | | param.put("vhost","__defaultVhost__"); |
| | | param.put("app",streamInfo.getApp()); |
| | | param.put("stream",streamInfo.getStreamId()); |
| | | param.put("stream",streamInfo.getStream()); |
| | | param.put("ssrc", sendRtpItem.getSsrc()); |
| | | param.put("dst_url",sendRtpItem.getIp()); |
| | | param.put("dst_port", sendRtpItem.getPort()); |
| | |
| | | try { |
| | | if (System.currentTimeMillis() - startTime < 30 * 1000) { |
| | | MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); |
| | | if (zlmrtpServerFactory.isStreamReady(mediaInfo, streamInfo.getApp(), streamInfo.getStreamId())) { |
| | | if (zlmrtpServerFactory.isStreamReady(mediaInfo, streamInfo.getApp(), streamInfo.getStream())) { |
| | | rtpPushed = true; |
| | | logger.info("已获取设备推流[{}/{}],开始向上级推流[{}:{}]", |
| | | streamInfo.getApp() ,streamInfo.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort()); |
| | | streamInfo.getApp() ,streamInfo.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort()); |
| | | zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); |
| | | } else { |
| | | logger.info("等待设备推流[{}/{}].......", |
| | | streamInfo.getApp() ,streamInfo.getStreamId()); |
| | | streamInfo.getApp() ,streamInfo.getStream()); |
| | | Thread.sleep(1000); |
| | | continue; |
| | | } |
| | | } else { |
| | | rtpPushed = true; |
| | | logger.info("设备推流[{}/{}]超时,终止向上级推流", |
| | | streamInfo.getApp() ,streamInfo.getStreamId()); |
| | | streamInfo.getApp() ,streamInfo.getStream()); |
| | | } |
| | | } catch (InterruptedException e) { |
| | | e.printStackTrace(); |
| | |
| | | redisCatchStorage.deleteSendRTPServer(platformGbId, channelId); |
| | | if (zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId) == 0) { |
| | | logger.info(streamId + "无其它观看者,通知设备停止推流"); |
| | | cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId); |
| | | cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId, streamId); |
| | | } |
| | | } |
| | | // 可能是设备主动停止 |
| | | Device device = storager.queryVideoDeviceByChannelId(platformGbId); |
| | | if (device != null) { |
| | | StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId); |
| | | |
| | | if (streamInfo != null) { |
| | | redisCatchStorage.stopPlay(streamInfo); |
| | | } |
| | | storager.stopPlay(device.getDeviceId(), channelId); |
| | | mediaServerService.closeRTPServer(device, channelId); |
| | | mediaServerService.closeRTPServer(device, channelId, streamInfo.getStream()); |
| | | } |
| | | } |
| | | } catch (SipException e) { |
| | |
| | | StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(device.getDeviceId(), "*"); |
| | | if (streamInfo != null) { |
| | | redisCatchStorage.stopPlayback(streamInfo); |
| | | cmder.streamByeCmd(streamInfo.getDeviceID(), streamInfo.getChannelId()); |
| | | cmder.streamByeCmd(streamInfo.getDeviceID(), streamInfo.getChannelId(), streamInfo.getStream()); |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | if (response.getStatusCode() == 401) { |
| | | WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME); |
| | | sipCommanderForPlatform.register(parentPlatform, callId, www, null, null); |
| | | sipCommanderForPlatform.register(parentPlatform, callId, www, null, null, true); |
| | | }else if (response.getStatusCode() == 200){ |
| | | // 注册/注销成功 |
| | | logger.info(String.format("%s %s成功", platformGBId, action)); |
| | |
| | | StreamPushItem streamPushItem = null;
|
| | | StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaServerItem, app, streamId, tracks);
|
| | | item.setStreamInfo(streamInfoByAppAndStream);
|
| | |
|
| | | redisCatchStorage.addStream(mediaServerItem, type, app, streamId, item);
|
| | | if (item.getOriginType() == OriginType.RTSP_PUSH.ordinal()
|
| | | || item.getOriginType() == OriginType.RTMP_PUSH.ordinal()
|
| | |
| | | if (redisCatchStorage.isChannelSendingRTP(streamInfoForPlayCatch.getChannelId())) {
|
| | | ret.put("close", false);
|
| | | } else {
|
| | | cmder.streamByeCmd(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId());
|
| | | cmder.streamByeCmd(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId(),
|
| | | streamInfoForPlayCatch.getStream());
|
| | | redisCatchStorage.stopPlay(streamInfoForPlayCatch);
|
| | | storager.stopPlay(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId());
|
| | | }
|
| | | }else{
|
| | | StreamInfo streamInfoForPlayBackCatch = redisCatchStorage.queryPlaybackByStreamId(streamId);
|
| | | if (streamInfoForPlayBackCatch != null) {
|
| | | cmder.streamByeCmd(streamInfoForPlayBackCatch.getDeviceID(), streamInfoForPlayBackCatch.getChannelId());
|
| | | cmder.streamByeCmd(streamInfoForPlayBackCatch.getDeviceID(),
|
| | | streamInfoForPlayBackCatch.getChannelId(), streamInfoForPlayBackCatch.getStream());
|
| | | redisCatchStorage.stopPlayback(streamInfoForPlayBackCatch);
|
| | | }else {
|
| | | StreamInfo streamInfoForDownload = redisCatchStorage.queryDownloadByStreamId(streamId);
|
| | |
| | | } |
| | | } |
| | | if (null != result && result){ |
| | | eventMap.remove(key); |
| | | // TODO 报错未处理 |
| | | iterator.remove(); |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean isPlayback); |
| | | |
| | | void closeRTPServer(Device device, String channelId); |
| | | void closeRTPServer(Device device, String channelId, String ssrc); |
| | | |
| | | void clearRTPServer(MediaServerItem mediaServerItem); |
| | | |
| | |
| | | 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; |
| | | import com.genersoft.iot.vmp.service.bean.PlayBackCallback; |
| | | import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; |
| | | import org.springframework.http.ResponseEntity; |
| | | import org.springframework.web.context.request.async.DeferredResult; |
| | | |
| | | /** |
| | | * 点播处理 |
| | | */ |
| | | public interface IPlayService { |
| | | |
| | | void onPublishHandlerForPlayBack(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid); |
| | | void onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid); |
| | | |
| | | PlayResult play(MediaServerItem mediaServerItem, String deviceId, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent); |
| | |
| | | MediaServerItem getNewMediaServerItem(Device device); |
| | | |
| | | void onPublishHandlerForDownload(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, String toString); |
| | | |
| | | DeferredResult<ResponseEntity<String>> playBack(String deviceId, String channelId, String startTime, String endTime, PlayBackCallback errorCallBack); |
| | | } |
New file |
| | |
| | | package com.genersoft.iot.vmp.service.bean; |
| | | |
| | | import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; |
| | | |
| | | public interface PlayBackCallback { |
| | | |
| | | void call(RequestMessage msg); |
| | | |
| | | } |
| | |
| | | |
| | | private int port; |
| | | private String ssrc; |
| | | private String StreamId; |
| | | private String Stream; |
| | | |
| | | public SSRCInfo(int port, String ssrc, String streamId) { |
| | | public SSRCInfo(int port, String ssrc, String stream) { |
| | | this.port = port; |
| | | this.ssrc = ssrc; |
| | | StreamId = streamId; |
| | | Stream = stream; |
| | | } |
| | | |
| | | public int getPort() { |
| | |
| | | this.ssrc = ssrc; |
| | | } |
| | | |
| | | public String getStreamId() { |
| | | return StreamId; |
| | | public String getStream() { |
| | | return Stream; |
| | | } |
| | | |
| | | public void setStreamId(String streamId) { |
| | | StreamId = streamId; |
| | | public void setStream(String stream) { |
| | | Stream = stream; |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void closeRTPServer(Device device, String channelId) { |
| | | String mediaServerId = streamSession.getMediaServerId(device.getDeviceId(), channelId); |
| | | public void closeRTPServer(Device device, String channelId, String stream) { |
| | | String mediaServerId = streamSession.getMediaServerId(device.getDeviceId(), channelId, stream); |
| | | String ssrc = streamSession.getSSRC(device.getDeviceId(), channelId, stream); |
| | | MediaServerItem mediaServerItem = this.getOne(mediaServerId); |
| | | if (mediaServerItem != null) { |
| | | String streamId = String.format("%s_%s", device.getDeviceId(), channelId); |
| | | zlmrtpServerFactory.closeRTPServer(mediaServerItem, streamId); |
| | | releaseSsrc(mediaServerItem, streamSession.getSSRC(device.getDeviceId(), channelId)); |
| | | releaseSsrc(mediaServerItem, ssrc); |
| | | } |
| | | streamSession.remove(device.getDeviceId(), channelId); |
| | | streamSession.remove(device.getDeviceId(), channelId, stream); |
| | | } |
| | | |
| | | @Override |
| | |
| | | @Override |
| | | public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String addr) { |
| | | StreamInfo streamInfoResult = new StreamInfo(); |
| | | streamInfoResult.setStreamId(stream); |
| | | streamInfoResult.setStream(stream); |
| | | streamInfoResult.setApp(app); |
| | | if (addr == null) { |
| | | addr = mediaInfo.getStreamIp(); |
| | |
| | | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| | | import com.genersoft.iot.vmp.service.IMediaServerService; |
| | | import com.genersoft.iot.vmp.service.bean.PlayBackCallback; |
| | | import com.genersoft.iot.vmp.service.bean.SSRCInfo; |
| | | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| | | import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
| | | import com.genersoft.iot.vmp.utils.redis.RedisUtil; |
| | | import com.genersoft.iot.vmp.vmanager.bean.WVPResult; |
| | | import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; |
| | | import com.genersoft.iot.vmp.service.IMediaService; |
| | |
| | | |
| | | @Autowired |
| | | private IRedisCatchStorage redisCatchStorage; |
| | | |
| | | @Autowired |
| | | private RedisUtil redis; |
| | | |
| | | @Autowired |
| | | private DeferredResultHolder resultHolder; |
| | |
| | | logger.warn(String.format("设备点播超时,deviceId:%s ,channelId:%s", deviceId, channelId)); |
| | | WVPResult wvpResult = new WVPResult(); |
| | | wvpResult.setCode(-1); |
| | | SIPDialog dialog = streamSession.getDialog(deviceId, channelId); |
| | | SIPDialog dialog = streamSession.getDialogByStream(deviceId, channelId, streamInfo.getStream()); |
| | | if (dialog != null) { |
| | | wvpResult.setMsg("收流超时,请稍候重试"); |
| | | }else { |
| | | wvpResult.setMsg("点播超时,请稍候重试"); |
| | | } |
| | | |
| | | msg.setData(wvpResult); |
| | | // 点播超时回复BYE |
| | | cmder.streamByeCmd(device.getDeviceId(), channelId); |
| | | cmder.streamByeCmd(device.getDeviceId(), channelId, streamInfo.getStream()); |
| | | // 释放rtpserver |
| | | mediaServerService.closeRTPServer(playResult.getDevice(), channelId); |
| | | mediaServerService.closeRTPServer(playResult.getDevice(), channelId, streamInfo.getStream()); |
| | | // 回复之前所有的点播请求 |
| | | resultHolder.invokeAllResult(msg); |
| | | // TODO 释放ssrc |
| | | }); |
| | | result.onCompletion(()->{ |
| | | // 点播结束时调用截图接口 |
| | |
| | | } |
| | | }); |
| | | if (streamInfo == null) { |
| | | SSRCInfo ssrcInfo; |
| | | String streamId = null; |
| | | if (mediaServerItem.isRtpEnable()) { |
| | | streamId = String.format("%s_%s", device.getDeviceId(), channelId); |
| | | } |
| | | |
| | | ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId); |
| | | |
| | | SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId); |
| | | // 发送点播消息 |
| | | cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInUse, JSONObject response) -> { |
| | | logger.info("收到订阅消息: " + response.toJSONString()); |
| | |
| | | WVPResult wvpResult = new WVPResult(); |
| | | wvpResult.setCode(-1); |
| | | // 点播返回sip错误 |
| | | mediaServerService.closeRTPServer(playResult.getDevice(), channelId); |
| | | mediaServerService.closeRTPServer(playResult.getDevice(), channelId, ssrcInfo.getStream()); |
| | | wvpResult.setMsg(String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg)); |
| | | msg.setData(wvpResult); |
| | | resultHolder.invokeAllResult(msg); |
| | |
| | | |
| | | }); |
| | | } else { |
| | | String streamId = streamInfo.getStreamId(); |
| | | String streamId = streamInfo.getStream(); |
| | | if (streamId == null) { |
| | | WVPResult wvpResult = new WVPResult(); |
| | | wvpResult.setCode(-1); |
| | |
| | | // TODO 点播前是否重置状态 |
| | | redisCatchStorage.stopPlay(streamInfo); |
| | | storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); |
| | | SSRCInfo ssrcInfo; |
| | | String streamId2 = null; |
| | | if (mediaServerItem.isRtpEnable()) { |
| | | streamId2 = String.format("%s_%s", device.getDeviceId(), channelId); |
| | | } |
| | | ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId2); |
| | | |
| | | SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId2); |
| | | cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> { |
| | | logger.info("收到订阅消息: " + response.toJSONString()); |
| | | onPublishHandlerForPlay(mediaServerItemInuse, response, deviceId, channelId, uuid); |
| | | }, (event) -> { |
| | | mediaServerService.closeRTPServer(playResult.getDevice(), channelId); |
| | | mediaServerService.closeRTPServer(playResult.getDevice(), channelId, ssrcInfo.getStream()); |
| | | WVPResult wvpResult = new WVPResult(); |
| | | wvpResult.setCode(-1); |
| | | wvpResult.setMsg(String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg)); |
| | |
| | | RequestMessage msg = new RequestMessage(); |
| | | msg.setId(uuid); |
| | | msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId); |
| | | StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid); |
| | | StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId); |
| | | if (streamInfo != null) { |
| | | DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); |
| | | if (deviceChannel != null) { |
| | | deviceChannel.setStreamId(streamInfo.getStreamId()); |
| | | storager.startPlay(deviceId, channelId, streamInfo.getStreamId()); |
| | | deviceChannel.setStreamId(streamInfo.getStream()); |
| | | storager.startPlay(deviceId, channelId, streamInfo.getStream()); |
| | | } |
| | | redisCatchStorage.startPlay(streamInfo); |
| | | msg.setData(JSON.toJSONString(streamInfo)); |
| | |
| | | |
| | | |
| | | @Override |
| | | public void onPublishHandlerForPlayBack(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) { |
| | | public DeferredResult<ResponseEntity<String>> playBack(String deviceId, String channelId, String startTime, String endTime, PlayBackCallback callback) { |
| | | String uuid = UUID.randomUUID().toString(); |
| | | String key = DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId; |
| | | DeferredResult<ResponseEntity<String>> result = new DeferredResult<>(30000L); |
| | | Device device = storager.queryVideoDevice(deviceId); |
| | | if (device == null) { |
| | | result.setResult(new ResponseEntity<>(HttpStatus.BAD_REQUEST)); |
| | | return result; |
| | | } |
| | | |
| | | MediaServerItem newMediaServerItem = getNewMediaServerItem(device); |
| | | SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, true); |
| | | resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId, uuid, result); |
| | | RequestMessage msg = new RequestMessage(); |
| | | msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId); |
| | | msg.setId(uuid); |
| | | StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid); |
| | | if (streamInfo != null) { |
| | | msg.setKey(key); |
| | | result.onTimeout(()->{ |
| | | msg.setData("回放超时"); |
| | | callback.call(msg); |
| | | }); |
| | | cmder.playbackStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, (MediaServerItem mediaServerItem, JSONObject response) -> { |
| | | logger.info("收到订阅消息: " + response.toJSONString()); |
| | | StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId); |
| | | if (streamInfo == null) { |
| | | logger.warn("设备回放API调用失败!"); |
| | | msg.setData("设备回放API调用失败!"); |
| | | callback.call(msg); |
| | | return; |
| | | } |
| | | redisCatchStorage.startPlayback(streamInfo); |
| | | msg.setData(JSON.toJSONString(streamInfo)); |
| | | resultHolder.invokeResult(msg); |
| | | } else { |
| | | logger.warn("设备回放API调用失败!"); |
| | | msg.setData("设备回放API调用失败!"); |
| | | resultHolder.invokeResult(msg); |
| | | } |
| | | callback.call(msg); |
| | | }, event -> { |
| | | msg.setData(String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg)); |
| | | callback.call(msg); |
| | | }); |
| | | return result; |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | |
| | | RequestMessage msg = new RequestMessage(); |
| | | msg.setKey(DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId); |
| | | msg.setId(uuid); |
| | | StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId, uuid); |
| | | StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId); |
| | | if (streamInfo != null) { |
| | | redisCatchStorage.startDownload(streamInfo); |
| | | msg.setData(JSON.toJSONString(streamInfo)); |
| | |
| | | } |
| | | |
| | | |
| | | public StreamInfo onPublishHandler(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) { |
| | | public StreamInfo onPublishHandler(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId) { |
| | | String streamId = resonse.getString("stream"); |
| | | JSONArray tracks = resonse.getJSONArray("tracks"); |
| | | StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem,"rtp", streamId, tracks); |
| | |
| | | }else { |
| | | streamLive = true; |
| | | StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream( |
| | | mediaInfo, param.getApp(), param.getStream(), null); |
| | | mediaInfo, param.getApp(), param.getStream(), null, null); |
| | | wvpResult.setData(streamInfo); |
| | | |
| | | } |
| | |
| | | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; |
| | | import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; |
| | | import com.genersoft.iot.vmp.service.bean.SSRCInfo; |
| | | import com.genersoft.iot.vmp.service.bean.ThirdPartyGB; |
| | | |
| | | import java.util.List; |
| | |
| | | void addMemInfo(double memInfo); |
| | | |
| | | void addNetInfo(Map<String, String> networkInterfaces); |
| | | |
| | | } |
| | |
| | | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; |
| | | import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; |
| | | import com.genersoft.iot.vmp.service.bean.SSRCInfo; |
| | | import com.genersoft.iot.vmp.service.bean.ThirdPartyGB; |
| | | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| | | import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; |
| | |
| | | */ |
| | | @Override |
| | | public boolean startPlay(StreamInfo stream) { |
| | | return redis.set(String.format("%S_%S_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX, userSetup.getServerId(), stream.getStreamId(),stream.getDeviceID(), stream.getChannelId()), |
| | | return redis.set(String.format("%S_%S_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX, userSetup.getServerId(), |
| | | stream.getStream(), stream.getDeviceID(), stream.getChannelId()), |
| | | stream); |
| | | } |
| | | |
| | |
| | | if (streamInfo == null) return false; |
| | | return redis.del(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX, |
| | | userSetup.getServerId(), |
| | | streamInfo.getStreamId(), |
| | | streamInfo.getStream(), |
| | | streamInfo.getDeviceID(), |
| | | streamInfo.getChannelId())); |
| | | } |
| | |
| | | return (StreamInfo)redis.get(String.format("%S_%s_%s_%s_%s", |
| | | VideoManagerConstants.PLAYER_PREFIX, |
| | | userSetup.getServerId(), |
| | | streamInfo.getStreamId(), |
| | | streamInfo.getStream(), |
| | | streamInfo.getDeviceID(), |
| | | streamInfo.getChannelId())); |
| | | } |
| | |
| | | |
| | | @Override |
| | | public boolean startPlayback(StreamInfo stream) { |
| | | return redis.set(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, userSetup.getServerId(),stream.getStreamId(), |
| | | stream.getDeviceID(), stream.getChannelId()), stream); |
| | | return redis.set(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, |
| | | userSetup.getServerId(), stream.getStream(), stream.getDeviceID(), stream.getChannelId()), stream); |
| | | } |
| | | |
| | | @Override |
| | | public boolean startDownload(StreamInfo streamInfo) { |
| | | return redis.set(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX, userSetup.getServerId(),streamInfo.getStreamId(), |
| | | streamInfo.getDeviceID(), streamInfo.getChannelId()), streamInfo); |
| | | return redis.set(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX, userSetup.getServerId(), |
| | | streamInfo.getStream(), streamInfo.getDeviceID(), streamInfo.getChannelId()), streamInfo); |
| | | } |
| | | |
| | | @Override |
| | |
| | | } |
| | | return redis.del(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, |
| | | userSetup.getServerId(), |
| | | streamInfo.getStreamId(), |
| | | streamInfo.getStream(), |
| | | streamInfo.getDeviceID(), |
| | | streamInfo.getChannelId())); |
| | | } |
| | |
| | | package com.genersoft.iot.vmp.storager.impl; |
| | | |
| | | import com.genersoft.iot.vmp.common.StreamInfo; |
| | | import com.genersoft.iot.vmp.conf.SipConfig; |
| | | import com.genersoft.iot.vmp.gb28181.bean.*; |
| | | import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
| | |
| | | public synchronized void updateChannel(String deviceId, DeviceChannel channel) { |
| | | String channelId = channel.getChannelId(); |
| | | channel.setDeviceId(deviceId); |
| | | channel.setStreamId(streamSession.getStreamId(deviceId, channel.getChannelId())); |
| | | StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); |
| | | if (streamInfo != null) { |
| | | channel.setStreamId(streamInfo.getStream()); |
| | | } |
| | | String now = this.format.format(System.currentTimeMillis()); |
| | | channel.setUpdateTime(now); |
| | | DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(deviceId, channelId); |
| | |
| | | if (channelList.size() == 0) { |
| | | for (DeviceChannel channel : channels) { |
| | | channel.setDeviceId(deviceId); |
| | | channel.setStreamId(streamSession.getStreamId(deviceId, channel.getChannelId())); |
| | | StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channel.getChannelId()); |
| | | if (streamInfo != null) { |
| | | channel.setStreamId(streamInfo.getStream()); |
| | | } |
| | | String now = this.format.format(System.currentTimeMillis()); |
| | | channel.setUpdateTime(now); |
| | | channel.setCreateTime(now); |
| | |
| | | channelsInStore.put(deviceChannel.getChannelId(), deviceChannel); |
| | | } |
| | | for (DeviceChannel channel : channels) { |
| | | String channelId = channel.getChannelId(); |
| | | channel.setDeviceId(deviceId); |
| | | channel.setStreamId(streamSession.getStreamId(deviceId, channel.getChannelId())); |
| | | StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channel.getChannelId()); |
| | | if (streamInfo != null) { |
| | | channel.setStreamId(streamInfo.getStream()); |
| | | } |
| | | String now = this.format.format(System.currentTimeMillis()); |
| | | channel.setUpdateTime(now); |
| | | if (channelsInStore.get(channel.getChannelId()) != null) { |
| | |
| | | String key = DeferredResultHolder.CALLBACK_CMD_STOP + deviceId + channelId; |
| | | resultHolder.put(key, uuid, result); |
| | | Device device = storager.queryVideoDevice(deviceId); |
| | | cmder.streamByeCmd(deviceId, channelId, (event) -> { |
| | | StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); |
| | | if (streamInfo == null) { |
| | | RequestMessage msg = new RequestMessage(); |
| | | msg.setId(uuid); |
| | | msg.setKey(key); |
| | | msg.setData("点播未找到"); |
| | | resultHolder.invokeAllResult(msg); |
| | | storager.stopPlay(deviceId, channelId); |
| | | }else { |
| | | redisCatchStorage.stopPlay(streamInfo); |
| | | storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); |
| | | RequestMessage msg = new RequestMessage(); |
| | | msg.setId(uuid); |
| | | msg.setKey(key); |
| | | //Response response = event.getResponse(); |
| | | msg.setData(String.format("success")); |
| | | resultHolder.invokeAllResult(msg); |
| | | } |
| | | mediaServerService.closeRTPServer(device, channelId); |
| | | StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); |
| | | if (streamInfo == null) { |
| | | RequestMessage msg = new RequestMessage(); |
| | | msg.setId(uuid); |
| | | msg.setKey(key); |
| | | msg.setData("点播未找到"); |
| | | resultHolder.invokeAllResult(msg); |
| | | storager.stopPlay(deviceId, channelId); |
| | | return result; |
| | | } |
| | | cmder.streamByeCmd(deviceId, channelId, streamInfo.getStream(), (event) -> { |
| | | redisCatchStorage.stopPlay(streamInfo); |
| | | storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); |
| | | RequestMessage msg = new RequestMessage(); |
| | | msg.setId(uuid); |
| | | msg.setKey(key); |
| | | //Response response = event.getResponse(); |
| | | msg.setData(String.format("success")); |
| | | resultHolder.invokeAllResult(msg); |
| | | mediaServerService.closeRTPServer(device, channelId, streamInfo.getStream()); |
| | | }); |
| | | |
| | | if (deviceId != null || channelId != null) { |
| | |
| | | jsonObject.put("deviceId", transaction.getDeviceId()); |
| | | jsonObject.put("channelId", transaction.getChannelId()); |
| | | jsonObject.put("ssrc", transaction.getSsrc()); |
| | | jsonObject.put("streamId", transaction.getStreamId()); |
| | | jsonObject.put("streamId", transaction.getStream()); |
| | | objects.add(jsonObject); |
| | | } |
| | | |
| | |
| | | StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, channelId); |
| | | if (streamInfo != null) { |
| | | // 停止之前的下载 |
| | | cmder.streamByeCmd(deviceId, channelId); |
| | | cmder.streamByeCmd(deviceId, channelId, streamInfo.getStream()); |
| | | } |
| | | |
| | | MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); |
| | |
| | | |
| | | cmder.downloadStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, (MediaServerItem mediaServerItem, JSONObject response) -> { |
| | | logger.info("收到订阅消息: " + response.toJSONString()); |
| | | playService.onPublishHandlerForDownload(mediaServerItem, response, deviceId, channelId, uuid.toString()); |
| | | playService.onPublishHandlerForDownload(mediaServerItem, response, deviceId, channelId, uuid); |
| | | }, event -> { |
| | | RequestMessage msg = new RequestMessage(); |
| | | msg.setId(uuid); |
| | |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class), |
| | | @ApiImplicitParam(name = "channelId", value = "通道ID", dataTypeClass = String.class), |
| | | @ApiImplicitParam(name = "stream", value = "流ID", dataTypeClass = String.class), |
| | | }) |
| | | @GetMapping("/stop/{deviceId}/{channelId}") |
| | | public ResponseEntity<String> playStop(@PathVariable String deviceId, @PathVariable String channelId) { |
| | | @GetMapping("/stop/{deviceId}/{channelId}/{stream}") |
| | | public ResponseEntity<String> playStop(@PathVariable String deviceId, @PathVariable String channelId, @PathVariable String stream) { |
| | | |
| | | cmder.streamByeCmd(deviceId, channelId); |
| | | cmder.streamByeCmd(deviceId, channelId, stream); |
| | | |
| | | if (logger.isDebugEnabled()) { |
| | | logger.debug(String.format("设备历史媒体下载停止 API调用,deviceId/channelId:%s_%s", deviceId, channelId)); |
| | |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.http.HttpStatus; |
| | | import org.springframework.http.ResponseEntity; |
| | | import org.springframework.util.StringUtils; |
| | | import org.springframework.web.bind.annotation.CrossOrigin; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.PathVariable; |
| | |
| | | if (logger.isDebugEnabled()) { |
| | | logger.debug(String.format("设备回放 API调用,deviceId:%s ,channelId:%s", deviceId, channelId)); |
| | | } |
| | | String uuid = UUID.randomUUID().toString(); |
| | | String key = DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId; |
| | | DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(30000L); |
| | | Device device = storager.queryVideoDevice(deviceId); |
| | | if (device == null) { |
| | | result.setResult(new ResponseEntity<>(HttpStatus.BAD_REQUEST)); |
| | | return result; |
| | | } |
| | | MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); |
| | | SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, true); |
| | | |
| | | // 超时处理 |
| | | result.onTimeout(()->{ |
| | | logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId)); |
| | | RequestMessage msg = new RequestMessage(); |
| | | msg.setId(uuid); |
| | | msg.setKey(key); |
| | | msg.setData("Timeout"); |
| | | resultHolder.invokeResult(msg); |
| | | }); |
| | | |
| | | StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, channelId); |
| | | if (streamInfo != null) { |
| | | // 停止之前的回放 |
| | | cmder.streamByeCmd(deviceId, channelId); |
| | | } |
| | | resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId, uuid, result); |
| | | |
| | | if (newMediaServerItem == null) { |
| | | logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId)); |
| | | RequestMessage msg = new RequestMessage(); |
| | | msg.setId(uuid); |
| | | msg.setKey(key); |
| | | msg.setData("Timeout"); |
| | | resultHolder.invokeResult(msg); |
| | | return result; |
| | | } |
| | | |
| | | cmder.playbackStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, (MediaServerItem mediaServerItem, JSONObject response) -> { |
| | | logger.info("收到订阅消息: " + response.toJSONString()); |
| | | playService.onPublishHandlerForPlayBack(mediaServerItem, response, deviceId, channelId, uuid.toString()); |
| | | }, event -> { |
| | | RequestMessage msg = new RequestMessage(); |
| | | msg.setId(uuid); |
| | | msg.setKey(key); |
| | | msg.setData(String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg)); |
| | | DeferredResult<ResponseEntity<String>> result = playService.playBack(deviceId, channelId, startTime, endTime, msg->{ |
| | | resultHolder.invokeResult(msg); |
| | | }); |
| | | |
| | |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class), |
| | | @ApiImplicitParam(name = "channelId", value = "通道ID", dataTypeClass = String.class), |
| | | @ApiImplicitParam(name = "stream", value = "流ID", dataTypeClass = String.class), |
| | | }) |
| | | @GetMapping("/stop/{deviceId}/{channelId}") |
| | | public ResponseEntity<String> playStop(@PathVariable String deviceId, @PathVariable String channelId) { |
| | | @GetMapping("/stop/{deviceId}/{channelId}/{stream}") |
| | | public ResponseEntity<String> playStop( |
| | | @PathVariable String deviceId, |
| | | @PathVariable String channelId, |
| | | @PathVariable String stream) { |
| | | |
| | | cmder.streamByeCmd(deviceId, channelId); |
| | | cmder.streamByeCmd(deviceId, channelId, stream); |
| | | |
| | | if (logger.isDebugEnabled()) { |
| | | logger.debug(String.format("设备录像回放停止 API调用,deviceId/channelId:%s/%s", deviceId, channelId)); |
| | | } |
| | | if (StringUtils.isEmpty(deviceId) || StringUtils.isEmpty(channelId) || StringUtils.isEmpty(stream)) { |
| | | return new ResponseEntity<>(HttpStatus.BAD_REQUEST); |
| | | } |
| | | |
| | | if (deviceId != null && channelId != null) { |
| | | JSONObject json = new JSONObject(); |
| | | json.put("deviceId", deviceId); |
| | | json.put("channelId", channelId); |
| | | return new ResponseEntity<String>(json.toString(), HttpStatus.OK); |
| | | return new ResponseEntity<>(json.toString(), HttpStatus.OK); |
| | | } else { |
| | | logger.warn("设备录像回放停止API调用失败!"); |
| | | return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR); |
| | | return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); |
| | | } |
| | | } |
| | | |
| | |
| | | PlayResult play = playService.play(newMediaServerItem, serial, code, (mediaServerItem, response)->{ |
| | | StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(serial, code); |
| | | JSONObject result = new JSONObject(); |
| | | result.put("StreamID", streamInfo.getStreamId()); |
| | | result.put("StreamID", streamInfo.getStream()); |
| | | result.put("DeviceID", device.getDeviceId()); |
| | | result.put("ChannelID", code); |
| | | result.put("ChannelName", deviceChannel.getName()); |
| | |
| | | result.put("error","未找到流信息"); |
| | | return result; |
| | | } |
| | | cmder.streamByeCmd(serial, code); |
| | | cmder.streamByeCmd(serial, code, streamInfo.getStream()); |
| | | redisCatchStorage.stopPlay(streamInfo); |
| | | storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); |
| | | return null; |
| | |
| | | <logger name="com.genersoft.iot.vmp.storager.dao" level="INFO"> |
| | | <appender-ref ref="STDOUT"/> |
| | | </logger> |
| | | <logger name="com.genersoft.iot.vmp.gb28181" level="DEBUG"> |
| | | <logger name="com.genersoft.iot.vmp.gb28181" level="INFO"> |
| | | <appender-ref ref="STDOUT"/> |
| | | </logger> |
| | | |
| | |
| | | this.isLoging = false; |
| | | // this.videoUrl = streamInfo.rtc; |
| | | this.videoUrl = this.getUrlByStreamInfo(streamInfo); |
| | | this.streamId = streamInfo.streamId; |
| | | this.streamId = streamInfo.stream; |
| | | this.app = streamInfo.app; |
| | | this.mediaServerId = streamInfo.mediaServerId; |
| | | this.playFromStreamInfo(false, streamInfo) |
| | |
| | | }).then(function (res) { |
| | | var streamInfo = res.data; |
| | | that.app = streamInfo.app; |
| | | that.streamId = streamInfo.streamId; |
| | | that.streamId = streamInfo.stream; |
| | | that.mediaServerId = streamInfo.mediaServerId; |
| | | that.ssrc = streamInfo.ssrc; |
| | | that.videoUrl = that.getUrlByStreamInfo(streamInfo); |
| | | that.recordPlay = true; |
| | | }); |
| | |
| | | this.videoUrl = ''; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: '/api/playback/stop/' + this.deviceId + "/" + this.channelId |
| | | url: '/api/playback/stop/' + this.deviceId + "/" + this.channelId + "/" + this.streamId |
| | | }).then(function (res) { |
| | | if (callback) callback() |
| | | }); |
| | |
| | | }).then(function (res) { |
| | | var streamInfo = res.data; |
| | | that.app = streamInfo.app; |
| | | that.streamId = streamInfo.streamId; |
| | | that.streamId = streamInfo.stream; |
| | | that.mediaServerId = streamInfo.mediaServerId; |
| | | that.videoUrl = that.getUrlByStreamInfo(streamInfo); |
| | | that.recordPlay = true; |
| | |
| | | this.videoUrl = ''; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: '/api/download/stop/' + this.deviceId + "/" + this.channelId |
| | | url: '/api/download/stop/' + this.deviceId + "/" + this.channelId+ "/" + this.streamId |
| | | }).then(function (res) { |
| | | if (callback) callback() |
| | | }); |
| | |
| | | let that = this; |
| | | this.$axios({ |
| | | method: 'post', |
| | | // url: '/api/ptz/' + this.deviceId + '/' + this.channelId + '?leftRight=' + leftRight + '&upDown=' + upDown + |
| | | // '&inOut=' + zoom + '&moveSpeed=50&zoomSpeed=50' |
| | | url: '/api/ptz/control/' + this.deviceId + '/' + this.channelId + '?command=' + command + '&horizonSpeed=' + this.controSpeed + '&verticalSpeed=' + this.controSpeed + '&zoomSpeed=' + this.controSpeed |
| | | }).then(function (res) {}); |
| | | }, |