|
|
@@ -1,15 +1,15 @@
|
|
|
package com.genersoft.iot.vmp.media.zlm;
|
|
|
|
|
|
+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.media.zlm.dto.MediaServerItem;
|
|
|
+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.stereotype.Component;
|
|
|
-import org.springframework.util.ObjectUtils;
|
|
|
|
|
|
import java.util.*;
|
|
|
|
|
|
@@ -24,6 +24,9 @@ public class ZLMRTPServerFactory {
|
|
|
@Autowired
|
|
|
private UserSetting userSetting;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private ZlmHttpHookSubscribe hookSubscribe;
|
|
|
+
|
|
|
private int[] portRangeArray = new int[2];
|
|
|
|
|
|
public int getFreePort(MediaServerItem mediaServerItem, int startPort, int endPort, List<Integer> usedFreelist) {
|
|
|
@@ -141,7 +144,7 @@ public class ZLMRTPServerFactory {
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
- public boolean closeRTPServer(MediaServerItem serverItem, String streamId) {
|
|
|
+ public boolean closeRtpServer(MediaServerItem serverItem, String streamId) {
|
|
|
boolean result = false;
|
|
|
if (serverItem !=null){
|
|
|
Map<String, Object> param = new HashMap<>();
|
|
|
@@ -161,32 +164,6 @@ public class ZLMRTPServerFactory {
|
|
|
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;
|
|
|
-// }
|
|
|
-// }
|
|
|
|
|
|
/**
|
|
|
* 创建一个国标推流
|
|
|
@@ -200,21 +177,15 @@ public class ZLMRTPServerFactory {
|
|
|
*/
|
|
|
public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String deviceId, String channelId, boolean tcp){
|
|
|
|
|
|
- // 使用RTPServer 功能找一个可用的端口
|
|
|
- String sendRtpPortRange = serverItem.getSendRtpPortRange();
|
|
|
- if (ObjectUtils.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;
|
|
|
+ // 默认为随机端口
|
|
|
+ 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);
|
|
|
@@ -242,21 +213,13 @@ public class ZLMRTPServerFactory {
|
|
|
* @return SendRtpItem
|
|
|
*/
|
|
|
public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String app, String stream, String channelId, boolean tcp){
|
|
|
- // 使用RTPServer 功能找一个可用的端口
|
|
|
- String sendRtpPortRange = serverItem.getSendRtpPortRange();
|
|
|
- if (ObjectUtils.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;
|
|
|
+ // 默认为随机端口
|
|
|
+ int localPort = 0;
|
|
|
+ if (userSetting.getGbSendStreamStrict()) {
|
|
|
+ localPort = keepPort(serverItem, ssrc);
|
|
|
+ if (localPort == 0) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
}
|
|
|
SendRtpItem sendRtpItem = new SendRtpItem();
|
|
|
sendRtpItem.setIp(ip);
|
|
|
@@ -273,6 +236,42 @@ public class ZLMRTPServerFactory {
|
|
|
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);
|
|
|
+ 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
|
|
|
*/
|
|
|
@@ -333,7 +332,7 @@ public class ZLMRTPServerFactory {
|
|
|
result= true;
|
|
|
logger.info("[停止RTP推流] 成功");
|
|
|
} else {
|
|
|
- logger.error("[停止RTP推流] 失败: {}, 参数:{}->\r\n{}",jsonObject.getString("msg"),jsonObject.toJSONString(param));
|
|
|
+ logger.error("[停止RTP推流] 失败: {}, 参数:{}->\r\n{}",jsonObject.getString("msg"), JSON.toJSON(param), jsonObject);
|
|
|
}
|
|
|
return result;
|
|
|
}
|