From ea08969bfcff38b8195282c77495eb1f8bd8eb07 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: 星期二, 15 三月 2022 15:37:22 +0800 Subject: [PATCH] 使用zlm原生的rtp随机端口配置 --- src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java | 8 +- src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java | 186 +++++++++++++++++++++++++++------------------ src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerConfig.java | 11 ++ src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java | 14 +-- src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java | 3 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java | 2 6 files changed, 136 insertions(+), 88 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java index fef3412..77b4b32 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java @@ -372,12 +372,12 @@ } } if (playTransaction == null) { - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, true); + String streamId = null; if (mediaServerItem.isRtpEnable()) { - sendRtpItem.setStreamId(String.format("%s_%s", device.getDeviceId(), channelId)); - }else { - sendRtpItem.setStreamId(ssrcInfo.getStream()); + streamId = String.format("%s_%s", device.getDeviceId(), channelId); } + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, true); + sendRtpItem.setStreamId(ssrcInfo.getStream()); // 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶� redisCatchStorage.updateSendRTPSever(sendRtpItem); playService.play(mediaServerItem, ssrcInfo, device, channelId, hookEvent, errorEvent, (code, msg)->{ 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 5d1e8af..276ee23 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 @@ -10,8 +10,7 @@ import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; -import java.util.HashMap; -import java.util.Map; +import java.util.*; @Component public class ZLMRTPServerFactory { @@ -23,54 +22,80 @@ private int[] portRangeArray = new int[2]; - public int createRTPServer(MediaServerItem mediaServerItem, String streamId) { - Map<String, Integer> currentStreams = new HashMap<>(); + 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); - currentStreams.put(dataItem.getString("stream_id"), dataItem.getInteger("port")); + usedFreelist.add(dataItem.getInteger("port")); } } - } - // 宸茬粡鍦ㄦ帹娴� - if (currentStreams.get(streamId) != null) { - Map<String, Object> closeRtpServerParam = new HashMap<>(); - closeRtpServerParam.put("stream_id", streamId); - zlmresTfulUtils.closeRtpServer(mediaServerItem, closeRtpServerParam); - currentStreams.remove(streamId); } Map<String, Object> param = new HashMap<>(); int result = -1; - // 涓嶈缃帹娴佺鍙g鍒欎娇鐢ㄩ殢鏈虹鍙� - if (!StringUtils.isEmpty(mediaServerItem.getSendRtpPortRange())){ - int newPort = getPortFromportRange(mediaServerItem); - 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", streamId); + param.put("stream_id", stream); + param.put("port", 0); JSONObject openRtpServerResultJson = zlmresTfulUtils.openRtpServer(mediaServerItem, param); if (openRtpServerResultJson != null) { - switch (openRtpServerResultJson.getInteger("code")){ - case 0: - result= openRtpServerResultJson.getInteger("port"); - break; - case -300: // id宸茬粡瀛樺湪, 鍙兘宸茬粡鍦ㄥ叾浠栫鍙f帹娴� - Map<String, Object> closeRtpServerParam = new HashMap<>(); - closeRtpServerParam.put("stream_id", streamId); - zlmresTfulUtils.closeRtpServer(mediaServerItem, closeRtpServerParam); - result = createRTPServer(mediaServerItem, streamId);; - break; - case -400: // 绔彛鍗犵敤 - result= createRTPServer(mediaServerItem, streamId); - break; - default: - logger.error("鍒涘缓RTP Server 澶辫触 {}: " + openRtpServerResultJson.getString("msg"), param.get("port")); - break; + 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) { + + Map<String, Object> param = new HashMap<>(); + int result = -1; + // 鎺ㄦ祦绔彛璁剧疆0鍒欎娇鐢ㄩ殢鏈虹鍙� + param.put("enable_tcp", 1); + param.put("stream_id", streamId); + param.put("port", 0); + JSONObject openRtpServerResultJson = zlmresTfulUtils.openRtpServer(mediaServerItem, param); + + if (openRtpServerResultJson != null) { + if (openRtpServerResultJson.getInteger("code") == 0) { + result= openRtpServerResultJson.getInteger("port"); + }else { + logger.error("鍒涘缓RTP Server 澶辫触 {}: " + openRtpServerResultJson.getString("msg"), param.get("port")); } }else { // 妫�鏌LM鐘舵�� @@ -99,32 +124,32 @@ return result; } - private int getPortFromportRange(MediaServerItem mediaServerItem) { - int currentPort = mediaServerItem.getCurrentPort(); - if (currentPort == 0) { - String[] portRangeStrArray = mediaServerItem.getSendRtpPortRange().split(","); - if (portRangeStrArray.length != 2) { - portRangeArray[0] = 30000; - portRangeArray[1] = 30500; - }else { - portRangeArray[0] = Integer.parseInt(portRangeStrArray[0]); - portRangeArray[1] = Integer.parseInt(portRangeStrArray[1]); - } - } - - if (currentPort == 0 || currentPort++ > portRangeArray[1]) { - currentPort = portRangeArray[0]; - mediaServerItem.setCurrentPort(currentPort); - return portRangeArray[0]; - } else { - if (currentPort % 2 == 1) { - currentPort++; - } - currentPort++; - mediaServerItem.setCurrentPort(currentPort); - return currentPort; - } - } +// private int getPortFromportRange(MediaServerItem mediaServerItem) { +// int currentPort = mediaServerItem.getCurrentPort(); +// if (currentPort == 0) { +// String[] portRangeStrArray = mediaServerItem.getSendRtpPortRange().split(","); +// if (portRangeStrArray.length != 2) { +// portRangeArray[0] = 30000; +// portRangeArray[1] = 30500; +// }else { +// portRangeArray[0] = Integer.parseInt(portRangeStrArray[0]); +// portRangeArray[1] = Integer.parseInt(portRangeStrArray[1]); +// } +// } +// +// if (currentPort == 0 || currentPort++ > portRangeArray[1]) { +// currentPort = portRangeArray[0]; +// mediaServerItem.setCurrentPort(currentPort); +// return portRangeArray[0]; +// } else { +// if (currentPort % 2 == 1) { +// currentPort++; +// } +// currentPort++; +// mediaServerItem.setCurrentPort(currentPort); +// return currentPort; +// } +// } /** * 鍒涘缓涓�涓浗鏍囨帹娴� @@ -139,13 +164,18 @@ public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String deviceId, String channelId, boolean tcp){ // 浣跨敤RTPServer 鍔熻兘鎵句竴涓彲鐢ㄧ殑绔彛 - String playSsrc = serverItem.getSsrcConfig().getPlaySsrc(); - int localPort = createRTPServer(serverItem, playSsrc); - if (localPort != -1) { - // TODO 楂樺苟鍙戞椂鍙兘鍥犱负鏈斁鍏ョ紦瀛樿�宻src鍐茬獊 - serverItem.getSsrcConfig().releaseSsrc(playSsrc); - closeRTPServer(serverItem, playSsrc); + String sendRtpPortRange = serverItem.getSendRtpPortRange(); + if (StringUtils.isEmpty(sendRtpPortRange)) { + return null; + } + String[] portRangeStrArray = serverItem.getSendRtpPortRange().split(","); + int localPort = -1; + if (portRangeStrArray.length != 2) { + localPort = getFreePort(serverItem, 30000, 30500, null); }else { + localPort = getFreePort(serverItem, Integer.parseInt(portRangeStrArray[0]), Integer.parseInt(portRangeStrArray[1]), null); + } + if (localPort == -1) { logger.error("娌℃湁鍙敤鐨勭鍙�"); return null; } @@ -174,13 +204,19 @@ * @return SendRtpItem */ public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String app, String stream, String channelId, boolean tcp){ - String playSsrc = serverItem.getSsrcConfig().getPlaySsrc(); - int localPort = createRTPServer(serverItem, playSsrc); - if (localPort != -1) { - // TODO 楂樺苟鍙戞椂鍙兘鍥犱负鏈斁鍏ョ紦瀛樿�宻src鍐茬獊 - serverItem.getSsrcConfig().releaseSsrc(ssrc); - closeRTPServer(serverItem, playSsrc); + // 浣跨敤RTPServer 鍔熻兘鎵句竴涓彲鐢ㄧ殑绔彛 + String sendRtpPortRange = serverItem.getSendRtpPortRange(); + if (StringUtils.isEmpty(sendRtpPortRange)) { + return null; + } + String[] portRangeStrArray = serverItem.getSendRtpPortRange().split(","); + int localPort = -1; + if (portRangeStrArray.length != 2) { + localPort = getFreePort(serverItem, 30000, 30500, null); }else { + localPort = getFreePort(serverItem, Integer.parseInt(portRangeStrArray[0]), Integer.parseInt(portRangeStrArray[1]), null); + } + if (localPort == -1) { logger.error("娌℃湁鍙敤鐨勭鍙�"); return null; } @@ -199,7 +235,7 @@ } /** - * 璋冪敤zlm RESTful API 鈥斺�� startSendRtp + * 璋冪敤zlm RESTFUL API 鈥斺�� startSendRtp */ public JSONObject startSendRtpStream(MediaServerItem mediaServerItem, Map<String, Object>param) { Boolean result = false; @@ -208,9 +244,9 @@ logger.error("RTP鎺ㄦ祦澶辫触: 璇锋鏌LM鏈嶅姟"); } else if (jsonObject.getInteger("code") == 0) { result= true; - logger.info("RTP鎺ㄦ祦[ {}/{} ]璇锋眰鎴愬姛锛屾湰鍦版帹娴佺鍙o細{}" ,param.get("app"), param.get("stream"), jsonObject.getString("local_port")); + logger.info("RTP鎺ㄦ祦鎴愬姛[ {}/{} ]锛屾湰鍦版帹娴佺鍙o細{}" ,param.get("app"), param.get("stream"), jsonObject.getString("local_port")); } else { - logger.error("RTP鎺ㄦ祦澶辫触: " + jsonObject.getString("msg")); + logger.error("RTP鎺ㄦ祦澶辫触: {}, 鍙傛暟锛歿}",jsonObject.getString("msg"),JSONObject.toJSON(param)); } return jsonObject; } @@ -265,7 +301,7 @@ result= true; logger.info("鍋滄RTP鎺ㄦ祦鎴愬姛"); } else { - logger.error("鍋滄RTP鎺ㄦ祦澶辫触: " + jsonObject.getString("msg")); + logger.error("RTP鎺ㄦ祦澶辫触: {}, 鍙傛暟锛歿}",jsonObject.getString("msg"),JSONObject.toJSON(param)); } return result; } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerConfig.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerConfig.java index 7e3da46..db4ab76 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerConfig.java @@ -194,6 +194,9 @@ @JSONField(name = "rtp_proxy.port") private int rtpProxyPort; + @JSONField(name = "rtp_proxy.port_range") + private String portRange; + @JSONField(name = "rtp_proxy.timeoutSec") private String rtpProxyTimeoutSec; @@ -802,4 +805,12 @@ public void setHookAliveInterval(int hookAliveInterval) { this.hookAliveInterval = hookAliveInterval; } + + public String getPortRange() { + return portRange; + } + + public void setPortRange(String portRange) { + this.portRange = portRange; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java index 260da27..181fc5b 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java @@ -91,7 +91,7 @@ streamNoneReaderDelayMS = zlmServerConfig.getGeneralStreamNoneReaderDelayMS(); hookAliveInterval = zlmServerConfig.getHookAliveInterval(); rtpEnable = false; // 榛樿浣跨敤鍗曠鍙�;鐩村埌鐢ㄦ埛鑷繁璁剧疆寮�鍚绔彛 - rtpPortRange = "30000,30500"; // 榛樿浣跨敤30000,30500浣滀负绾ц仈鏃跺彂閫佹祦鐨勭鍙e彿 + rtpPortRange = zlmServerConfig.getPortRange().replace("_",","); // 榛樿浣跨敤30000,30500浣滀负绾ц仈鏃跺彂閫佹祦鐨勭鍙e彿 sendRtpPortRange = "30000,30500"; // 榛樿浣跨敤30000,30500浣滀负绾ц仈鏃跺彂閫佹祦鐨勭鍙e彿 recordAssistPort = 0; // 榛樿鍏抽棴 diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java index d369587..43312a8 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java @@ -521,6 +521,9 @@ // 鏈�澶氱瓑寰呮湭鍒濆鍖栫殑Track鏃堕棿锛屽崟浣嶆绉掞紝瓒呮椂涔嬪悗浼氬拷鐣ユ湭鍒濆鍖栫殑Track, 璁剧疆姝ら�夐」浼樺寲閭d簺闊抽閿欒鐨勪笉瑙勮寖娴侊紝 // 绛墇lm鏀寔缁欐瘡涓猺tpServer璁剧疆鍏抽棴闊抽鐨勬椂鍊欏彲浠ヤ笉璁剧疆姝ら�夐」 param.put("general.wait_track_ready_ms", "3000" ); + if (mediaServerItem.isRtpEnable() && !StringUtils.isEmpty(mediaServerItem.getRtpPortRange())) { + param.put("rtp_proxy.port_range", mediaServerItem.getRtpPortRange().replace(",", "-")); + } JSONObject responseJSON = zlmresTfulUtils.setServerConfig(mediaServerItem, param); diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java index 16e8eec..930bb33 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java @@ -109,7 +109,6 @@ // 褰曞儚鏌ヨ浠hannelId浣滀负deviceId鏌ヨ String key = DeferredResultHolder.CALLBACK_CMD_STOP + deviceId + channelId; resultHolder.put(key, uuid, result); - Device device = storager.queryVideoDevice(deviceId); StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); if (streamInfo == null) { RequestMessage msg = new RequestMessage(); @@ -120,15 +119,14 @@ storager.stopPlay(deviceId, channelId); return result; } - cmder.streamByeCmd(deviceId, channelId, streamInfo.getStream(), null, (event) -> { + cmder.streamByeCmd(deviceId, channelId, streamInfo.getStream(), null, eventResult -> { 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); + RequestMessage msgForSuccess = new RequestMessage(); + msgForSuccess.setId(uuid); + msgForSuccess.setKey(key); + msgForSuccess.setData(String.format("success")); + resultHolder.invokeAllResult(msgForSuccess); }); if (deviceId != null || channelId != null) { -- Gitblit v1.8.0