From c3ce2bc5d069ba57309567aee4ae418bc0cf75ed Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: 星期五, 17 三月 2023 13:22:05 +0800 Subject: [PATCH] 优化异常处理以及级联设备状态查询 --- src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java | 355 ++++++++++++++++++++++++++++++++++++++++++++--------------- 1 files changed, 265 insertions(+), 90 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java index 00951ba..9bf1a3a 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java @@ -1,102 +1,172 @@ package com.genersoft.iot.vmp.media.zlm; -import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; -import com.genersoft.iot.vmp.gb28181.session.SsrcUtil; +import com.genersoft.iot.vmp.media.zlm.dto.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; -import java.util.HashMap; -import java.util.Map; +import java.util.*; @Component public class ZLMRTPServerFactory { private Logger logger = LoggerFactory.getLogger("ZLMRTPServerFactory"); - @Value("${media.rtp.udpPortRange}") - private String udpPortRange; - @Autowired private ZLMRESTfulUtils zlmresTfulUtils; - private int[] udpPortRangeArray = new int[2]; + @Autowired + private UserSetting userSetting; - private int currentPort = 0; + @Autowired + private ZlmHttpHookSubscribe hookSubscribe; - public int createRTPServer(String streamId) { + private int[] portRangeArray = new int[2]; + + public int getFreePort(MediaServerItem mediaServerItem, int startPort, int endPort, List<Integer> usedFreelist) { + if (endPort <= startPort) { + return -1; + } + if (usedFreelist == null) { + usedFreelist = new ArrayList<>(); + } + JSONObject listRtpServerJsonResult = zlmresTfulUtils.listRtpServer(mediaServerItem); + if (listRtpServerJsonResult != null) { + JSONArray data = listRtpServerJsonResult.getJSONArray("data"); + if (data != null) { + for (int i = 0; i < data.size(); i++) { + JSONObject dataItem = data.getJSONObject(i); + usedFreelist.add(dataItem.getInteger("port")); + } + } + } + Map<String, Object> param = new HashMap<>(); int result = -1; - int newPort = getPortFromUdpPortRange(); - param.put("port", newPort); + // 璁剧疆鎺ㄦ祦绔彛 + if (startPort%2 == 1) { + startPort ++; + } + boolean checkPort = false; + for (int i = startPort; i < endPort + 1; i+=2) { + if (!usedFreelist.contains(i)){ + checkPort = true; + startPort = i; + break; + } + } + if (!checkPort) { + logger.warn("鏈壘鍒拌妭鐐箋}涓婅寖鍥碵{}-{}]鐨勭┖闂茬鍙�", mediaServerItem.getId(), startPort, endPort); + return -1; + } + param.put("port", startPort); + String stream = UUID.randomUUID().toString(); + param.put("enable_tcp", 1); + param.put("stream_id", stream); +// param.put("port", 0); + JSONObject openRtpServerResultJson = zlmresTfulUtils.openRtpServer(mediaServerItem, param); + + if (openRtpServerResultJson != null) { + if (openRtpServerResultJson.getInteger("code") == 0) { + result= openRtpServerResultJson.getInteger("port"); + Map<String, Object> closeRtpServerParam = new HashMap<>(); + closeRtpServerParam.put("stream_id", stream); + zlmresTfulUtils.closeRtpServer(mediaServerItem, closeRtpServerParam); + }else { + usedFreelist.add(startPort); + startPort +=2; + result = getFreePort(mediaServerItem, startPort, endPort,usedFreelist); + } + }else { + // 妫�鏌LM鐘舵�� + logger.error("鍒涘缓RTP Server 澶辫触 {}: 璇锋鏌LM鏈嶅姟", param.get("port")); + } + return result; + } + + public int createRTPServer(MediaServerItem mediaServerItem, String streamId, int ssrc, Integer port) { + int result = -1; + // 鏌ヨ姝tp server 鏄惁宸茬粡瀛樺湪 + JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaServerItem, streamId); + logger.info(JSONObject.toJSONString(rtpInfo)); + if(rtpInfo.getInteger("code") == 0){ + if (rtpInfo.getBoolean("exist")) { + result = rtpInfo.getInteger("local_port"); + if (result == 0) { + // 姝ゆ椂璇存槑rtpServer宸茬粡鍒涘缓浣嗘槸娴佽繕娌℃湁鎺ㄤ笂鏉� + // 姝ゆ椂閲嶆柊鎵撳紑rtpServer + Map<String, Object> param = new HashMap<>(); + param.put("stream_id", streamId); + JSONObject jsonObject = zlmresTfulUtils.closeRtpServer(mediaServerItem, param); + if (jsonObject != null ) { + if (jsonObject.getInteger("code") == 0) { + return createRTPServer(mediaServerItem, streamId, ssrc, port); + }else { + logger.warn("[寮�鍚痳tpServer], 閲嶅惎RtpServer閿欒"); + } + } + } + return result; + } + }else if(rtpInfo.getInteger("code") == -2){ + return result; + } + + Map<String, Object> param = new HashMap<>(); + param.put("enable_tcp", 1); param.put("stream_id", streamId); - JSONObject jsonObject = zlmresTfulUtils.openRtpServer(param); - System.out.println(jsonObject); - - if (jsonObject != null) { - switch (jsonObject.getInteger("code")){ - case 0: - result= newPort; - break; - case -300: // id宸茬粡瀛樺湪 - result = newPort; - break; - case -400: // 绔彛鍗犵敤 - result= createRTPServer(streamId); - break; - default: - logger.error("鍒涘缓RTP Server 澶辫触: " + jsonObject.getString("msg")); - break; - } + // 鎺ㄦ祦绔彛璁剧疆0鍒欎娇鐢ㄩ殢鏈虹鍙� + if (port == null) { + param.put("port", 0); }else { - // 妫�鏌LM鐘舵�� - logger.error("鍒涘缓RTP Server 澶辫触: 璇锋鏌LM鏈嶅姟"); + param.put("port", port); } - return result; - } - - public boolean closeRTPServer(String streamId) { - boolean result = false; - Map<String, Object> param = new HashMap<>(); - param.put("stream_id", streamId); - JSONObject jsonObject = zlmresTfulUtils.closeRtpServer(param); - if (jsonObject != null ) { - if (jsonObject.getInteger("code") == 0) { - result = jsonObject.getInteger("hit") == 1; + param.put("ssrc", ssrc); + JSONObject openRtpServerResultJson = zlmresTfulUtils.openRtpServer(mediaServerItem, param); + logger.info(JSONObject.toJSONString(openRtpServerResultJson)); + if (openRtpServerResultJson != null) { + if (openRtpServerResultJson.getInteger("code") == 0) { + result= openRtpServerResultJson.getInteger("port"); }else { - logger.error("鍏抽棴RTP Server 澶辫触: " + jsonObject.getString("msg")); + logger.error("鍒涘缓RTP Server 澶辫触 {}: ", openRtpServerResultJson.getString("msg")); } }else { // 妫�鏌LM鐘舵�� - logger.error("鍏抽棴RTP Server 澶辫触: 璇锋鏌LM鏈嶅姟"); + logger.error("鍒涘缓RTP Server 澶辫触 {}: 璇锋鏌LM鏈嶅姟", param.get("port")); } return result; } - private int getPortFromUdpPortRange() { - if (currentPort == 0) { - String[] udpPortRangeStrArray = udpPortRange.split(","); - udpPortRangeArray[0] = Integer.parseInt(udpPortRangeStrArray[0]); - udpPortRangeArray[1] = Integer.parseInt(udpPortRangeStrArray[1]); - } - - if (currentPort == 0 || currentPort++ > udpPortRangeArray[1]) { - currentPort = udpPortRangeArray[0]; - return udpPortRangeArray[0]; - } else { - if (currentPort % 2 == 1) { - currentPort++; + public boolean closeRtpServer(MediaServerItem serverItem, String streamId) { + boolean result = false; + if (serverItem !=null){ + Map<String, Object> param = new HashMap<>(); + param.put("stream_id", streamId); + JSONObject jsonObject = zlmresTfulUtils.closeRtpServer(serverItem, param); + if (jsonObject != null ) { + if (jsonObject.getInteger("code") == 0) { + result = jsonObject.getInteger("hit") == 1; + }else { + logger.error("鍏抽棴RTP Server 澶辫触: " + jsonObject.getString("msg")); + } + }else { + // 妫�鏌LM鐘舵�� + logger.error("鍏抽棴RTP Server 澶辫触: 璇锋鏌LM鏈嶅姟"); } - return currentPort++; } + return result; } + /** - * 鍒涘缓涓�涓帹娴� + * 鍒涘缓涓�涓浗鏍囨帹娴� * @param ip 鎺ㄦ祦ip * @param port 鎺ㄦ祦绔彛 * @param ssrc 鎺ㄦ祦鍞竴鏍囪瘑 @@ -105,14 +175,17 @@ * @param tcp 鏄惁涓簍cp * @return SendRtpItem */ - public SendRtpItem createSendRtpItem(String ip, int port, String ssrc, String platformId, String deviceId, String channelId, boolean tcp){ - String playSsrc = SsrcUtil.getPlaySsrc(); - int localPort = createRTPServer(SsrcUtil.getPlaySsrc()); - if (localPort != -1) { - closeRTPServer(playSsrc); - }else { - logger.error("娌℃湁鍙敤鐨勭鍙�"); - return null; + public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String deviceId, String channelId, boolean tcp, boolean rtcp){ + + // 榛樿涓洪殢鏈虹鍙� + int localPort = 0; + if (userSetting.getGbSendStreamStrict()) { + if (userSetting.getGbSendStreamStrict()) { + localPort = keepPort(serverItem, ssrc); + if (localPort == 0) { + return null; + } + } } SendRtpItem sendRtpItem = new SendRtpItem(); sendRtpItem.setIp(ip); @@ -122,51 +195,153 @@ sendRtpItem.setDeviceId(deviceId); sendRtpItem.setChannelId(channelId); sendRtpItem.setTcp(tcp); + sendRtpItem.setRtcp(rtcp); + sendRtpItem.setApp("rtp"); sendRtpItem.setLocalPort(localPort); + sendRtpItem.setServerId(userSetting.getServerId()); + sendRtpItem.setMediaServerId(serverItem.getId()); return sendRtpItem; } /** - * 璋冪敤zlm RESTful API 鈥斺�� startSendRtp + * 鍒涘缓涓�涓洿鎾帹娴� + * @param ip 鎺ㄦ祦ip + * @param port 鎺ㄦ祦绔彛 + * @param ssrc 鎺ㄦ祦鍞竴鏍囪瘑 + * @param platformId 骞冲彴id + * @param channelId 閫氶亾id + * @param tcp 鏄惁涓簍cp + * @return SendRtpItem */ - public Boolean startSendRtpStream(Map<String, Object>param) { - Boolean result = false; - JSONObject jsonObject = zlmresTfulUtils.startSendRtp(param); - System.out.println(jsonObject); - if (jsonObject == null) { - logger.error("RTP鎺ㄦ祦澶辫触: 璇锋鏌LM鏈嶅姟"); - } else if (jsonObject.getInteger("code") == 0) { - result= true; - logger.error("RTP鎺ㄦ祦璇锋眰鎴愬姛锛屾湰鍦版帹娴佺鍙o細" + jsonObject.getString("local_port")); - } else { - logger.error("RTP鎺ㄦ祦澶辫触: " + jsonObject.getString("msg")); + public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String app, String stream, String channelId, boolean tcp, boolean rtcp){ + // 榛樿涓洪殢鏈虹鍙� + int localPort = 0; + if (userSetting.getGbSendStreamStrict()) { + localPort = keepPort(serverItem, ssrc); + if (localPort == 0) { + return null; + } } - return result; + SendRtpItem sendRtpItem = new SendRtpItem(); + sendRtpItem.setIp(ip); + sendRtpItem.setPort(port); + sendRtpItem.setSsrc(ssrc); + sendRtpItem.setApp(app); + sendRtpItem.setStreamId(stream); + sendRtpItem.setPlatformId(platformId); + sendRtpItem.setChannelId(channelId); + sendRtpItem.setTcp(tcp); + sendRtpItem.setLocalPort(localPort); + sendRtpItem.setServerId(userSetting.getServerId()); + sendRtpItem.setMediaServerId(serverItem.getId()); + sendRtpItem.setRtcp(rtcp); + return sendRtpItem; + } + + /** + * 淇濇寔绔彛锛岀洿鍒伴渶瑕侀渶瑕佸彂娴佹椂鍐嶉噴鏀� + */ + public int keepPort(MediaServerItem serverItem, String ssrc) { + int localPort = 0; + Map<String, Object> param = new HashMap<>(3); + param.put("port", 0); + param.put("enable_tcp", 1); + param.put("stream_id", ssrc); + JSONObject jsonObject = zlmresTfulUtils.openRtpServer(serverItem, param); + if (jsonObject.getInteger("code") == 0) { + localPort = jsonObject.getInteger("port"); + HookSubscribeForRtpServerTimeout hookSubscribeForRtpServerTimeout = HookSubscribeFactory.on_rtp_server_timeout(ssrc, null, serverItem.getId()); + // 璁㈤槄 zlm鍚姩浜嬩欢, 鏂扮殑zlm涔熶細浠庤繖閲岃繘鍏ョ郴缁� + hookSubscribe.addSubscribe(hookSubscribeForRtpServerTimeout, + (MediaServerItem mediaServerItem, JSONObject response)->{ + logger.info("[涓婄骇鐐规挱] {}->鐩戝惉绔彛鍒版湡缁х画淇濇寔鐩戝惉", ssrc); + keepPort(serverItem, ssrc); + }); + logger.info("[涓婄骇鐐规挱] {}->鐩戝惉绔彛: {}", ssrc, localPort); + }else { + logger.info("[涓婄骇鐐规挱] 鐩戝惉绔彛澶辫触: {}", ssrc); + } + return localPort; + } + + /** + * 閲婃斁淇濇寔鐨勭鍙� + */ + public boolean releasePort(MediaServerItem serverItem, String ssrc) { + logger.info("[涓婄骇鐐规挱] {}->閲婃斁鐩戝惉绔彛", ssrc); + boolean closeRTPServerResult = closeRtpServer(serverItem, ssrc); + HookSubscribeForRtpServerTimeout hookSubscribeForRtpServerTimeout = HookSubscribeFactory.on_rtp_server_timeout(ssrc, null, serverItem.getId()); + // 璁㈤槄 zlm鍚姩浜嬩欢, 鏂扮殑zlm涔熶細浠庤繖閲岃繘鍏ョ郴缁� + hookSubscribe.removeSubscribe(hookSubscribeForRtpServerTimeout); + return closeRTPServerResult; + } + + /** + * 璋冪敤zlm RESTFUL API 鈥斺�� startSendRtp + */ + public JSONObject startSendRtpStream(MediaServerItem mediaServerItem, Map<String, Object>param) { + return zlmresTfulUtils.startSendRtp(mediaServerItem, param); } /** * 鏌ヨ寰呰浆鎺ㄧ殑娴佹槸鍚﹀氨缁� */ - public Boolean isRtpReady(String streamId) { - JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo("rtp", "rtmp", streamId); + public Boolean isRtpReady(MediaServerItem mediaServerItem, String streamId) { + JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem,"rtp", "rtsp", streamId); return (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online")); + } + + /** + * 鏌ヨ寰呰浆鎺ㄧ殑娴佹槸鍚﹀氨缁� + */ + public Boolean isStreamReady(MediaServerItem mediaServerItem, String app, String streamId) { + JSONObject mediaInfo = zlmresTfulUtils.getMediaList(mediaServerItem, app, streamId); + return mediaInfo != null && (mediaInfo.getInteger("code") == 0 + + && mediaInfo.getJSONArray("data") != null + && mediaInfo.getJSONArray("data").size() > 0); + } + + /** + * 鏌ヨ杞帹鐨勬祦鏄惁鏈夊叾瀹冭鐪嬭�� + * @param streamId + * @return + */ + public int totalReaderCount(MediaServerItem mediaServerItem, String app, String streamId) { + JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtsp", streamId); + if (mediaInfo == null) { + return 0; + } + Integer code = mediaInfo.getInteger("code"); + if ( code < 0) { + logger.warn("鏌ヨ娴�({}/{})鏄惁鏈夊叾瀹冭鐪嬭�呮椂寰楀埌锛� {}", app, streamId, mediaInfo.getString("msg")); + return -1; + } + if ( code == 0 && mediaInfo.getBoolean("online") != null && !mediaInfo.getBoolean("online")) { + logger.warn("鏌ヨ娴�({}/{})鏄惁鏈夊叾瀹冭鐪嬭�呮椂寰楀埌锛� {}", app, streamId, mediaInfo.getString("msg")); + return -1; + } + return mediaInfo.getInteger("totalReaderCount"); } /** * 璋冪敤zlm RESTful API 鈥斺�� stopSendRtp */ - public Boolean stopSendRtpStream(Map<String, Object>param) { + public Boolean stopSendRtpStream(MediaServerItem mediaServerItem, Map<String, Object>param) { Boolean result = false; - JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(param); - System.out.println(jsonObject); + JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(mediaServerItem, param); if (jsonObject == null) { - logger.error("鍋滄RTP鎺ㄦ祦澶辫触: 璇锋鏌LM鏈嶅姟"); + logger.error("[鍋滄RTP鎺ㄦ祦] 澶辫触: 璇锋鏌LM鏈嶅姟"); } else if (jsonObject.getInteger("code") == 0) { result= true; - logger.error("鍋滄RTP鎺ㄦ祦鎴愬姛"); + logger.info("[鍋滄RTP鎺ㄦ祦] 鎴愬姛"); } else { - logger.error("鍋滄RTP鎺ㄦ祦澶辫触: " + jsonObject.getString("msg")); + logger.error("[鍋滄RTP鎺ㄦ祦] 澶辫触: {}, 鍙傛暟锛歿}->\r\n{}",jsonObject.getString("msg"), JSON.toJSON(param), jsonObject); } return result; } + + public void closeAllSendRtpStream() { + + } } -- Gitblit v1.8.0