Commit 04e7f48fde1b1a653d413eb41186ec7354f5ae31

Authored by 648540858
1 parent 88584224

合并主线的发流端口管理逻辑

sql/2.6.8补丁更新.sql 0 → 100644
  1 +alter table media_server
  2 + add sendRtpPortRange varchar(50) not null;
0 \ No newline at end of file 3 \ No newline at end of file
src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java
@@ -75,6 +75,9 @@ public class MediaConfig{ @@ -75,6 +75,9 @@ public class MediaConfig{
75 @Value("${media.rtp.port-range}") 75 @Value("${media.rtp.port-range}")
76 private String rtpPortRange; 76 private String rtpPortRange;
77 77
  78 + @Value("${media.rtp.send-port-range}")
  79 + private String rtpSendPortRange;
  80 +
78 @Value("${media.record-assist-port:0}") 81 @Value("${media.record-assist-port:0}")
79 private Integer recordAssistPort = 0; 82 private Integer recordAssistPort = 0;
80 83
@@ -206,6 +209,7 @@ public class MediaConfig{ @@ -206,6 +209,7 @@ public class MediaConfig{
206 mediaServerItem.setSecret(secret); 209 mediaServerItem.setSecret(secret);
207 mediaServerItem.setRtpEnable(rtpEnable); 210 mediaServerItem.setRtpEnable(rtpEnable);
208 mediaServerItem.setRtpPortRange(rtpPortRange); 211 mediaServerItem.setRtpPortRange(rtpPortRange);
  212 + mediaServerItem.setSendRtpPortRange(rtpSendPortRange);
209 mediaServerItem.setRecordAssistPort(recordAssistPort); 213 mediaServerItem.setRecordAssistPort(recordAssistPort);
210 mediaServerItem.setHookAliveInterval(30.00f); 214 mediaServerItem.setHookAliveInterval(30.00f);
211 215
@@ -222,4 +226,11 @@ public class MediaConfig{ @@ -222,4 +226,11 @@ public class MediaConfig{
222 return false; 226 return false;
223 } 227 }
224 228
  229 + public String getRtpSendPortRange() {
  230 + return rtpSendPortRange;
  231 + }
  232 +
  233 + public void setRtpSendPortRange(String rtpSendPortRange) {
  234 + this.rtpSendPortRange = rtpSendPortRange;
  235 + }
225 } 236 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
@@ -140,15 +140,7 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In @@ -140,15 +140,7 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
140 startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, jsonObject, param, callIdHeader); 140 startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, jsonObject, param, callIdHeader);
141 }); 141 });
142 }else { 142 }else {
143 - // 如果是非严格模式,需要关闭端口占用  
144 - JSONObject startSendRtpStreamResult = null;  
145 - if (sendRtpItem.getLocalPort() != 0) {  
146 - if (zlmrtpServerFactory.releasePort(mediaInfo, sendRtpItem.getSsrc())) {  
147 - startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param);  
148 - }  
149 - }else {  
150 - startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param);  
151 - } 143 + JSONObject startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param);
152 if (startSendRtpStreamResult != null) { 144 if (startSendRtpStreamResult != null) {
153 startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, startSendRtpStreamResult, param, callIdHeader); 145 startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, startSendRtpStreamResult, param, callIdHeader);
154 } 146 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
@@ -349,9 +349,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -349,9 +349,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
349 } 349 }
350 logger.info("[上级Invite] {}, 平台:{}, 通道:{}, 收流地址:{}:{},收流方式:{}, ssrc:{}", sessionName, username, channelId, addressStr, port, streamTypeStr, ssrc); 350 logger.info("[上级Invite] {}, 平台:{}, 通道:{}, 收流地址:{}:{},收流方式:{}, ssrc:{}", sessionName, username, channelId, addressStr, port, streamTypeStr, ssrc);
351 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, 351 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
352 - device.getDeviceId(), channelId, mediaTransmissionTCP, platform.isRtcp(), ssrcFromCallback -> {  
353 - return redisCatchStorage.querySendRTPServer(platform.getServerGBId(), channelId, null, callIdHeader.getCallId()) != null;  
354 - }); 352 + device.getDeviceId(), channelId, mediaTransmissionTCP, platform.isRtcp());
355 353
356 if (tcpActive != null) { 354 if (tcpActive != null) {
357 sendRtpItem.setTcpActive(tcpActive); 355 sendRtpItem.setTcpActive(tcpActive);
@@ -553,9 +551,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -553,9 +551,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
553 if (streamReady) { 551 if (streamReady) {
554 // 自平台内容 552 // 自平台内容
555 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, 553 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
556 - gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp(), ssrcFromCallback ->{  
557 - return redisCatchStorage.querySendRTPServer(platform.getServerGBId(), channelId, null, callIdHeader.getCallId()) != null;  
558 - }); 554 + gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp());
559 555
560 if (sendRtpItem == null) { 556 if (sendRtpItem == null) {
561 logger.warn("服务器端口资源不足"); 557 logger.warn("服务器端口资源不足");
@@ -594,9 +590,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -594,9 +590,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
594 if (streamReady) { 590 if (streamReady) {
595 // 自平台内容 591 // 自平台内容
596 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, 592 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
597 - gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp(), ssrcFromCallback ->{  
598 - return redisCatchStorage.querySendRTPServer(platform.getServerGBId(), channelId, null, callIdHeader.getCallId()) != null;  
599 - }); 593 + gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp());
600 594
601 if (sendRtpItem == null) { 595 if (sendRtpItem == null) {
602 logger.warn("服务器端口资源不足"); 596 logger.warn("服务器端口资源不足");
@@ -713,9 +707,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -713,9 +707,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
713 dynamicTask.stop(callIdHeader.getCallId()); 707 dynamicTask.stop(callIdHeader.getCallId());
714 if (serverId.equals(userSetting.getServerId())) { 708 if (serverId.equals(userSetting.getServerId())) {
715 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, finalPort, ssrc, requesterId, 709 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, finalPort, ssrc, requesterId,
716 - app, stream, channelId, mediaTransmissionTCP, platform.isRtcp(), ssrcFromCallback -> {  
717 - return redisCatchStorage.querySendRTPServer(platform.getServerGBId(), channelId, null, callIdHeader.getCallId()) != null;  
718 - }); 710 + app, stream, channelId, mediaTransmissionTCP, platform.isRtcp());
719 711
720 if (sendRtpItem == null) { 712 if (sendRtpItem == null) {
721 logger.warn("上级点时创建sendRTPItem失败,可能是服务器端口资源不足"); 713 logger.warn("上级点时创建sendRTPItem失败,可能是服务器端口资源不足");
src/main/java/com/genersoft/iot/vmp/media/zlm/SendRtpPortManager.java 0 → 100644
  1 +package com.genersoft.iot.vmp.media.zlm;
  2 +
  3 +import com.genersoft.iot.vmp.conf.UserSetting;
  4 +import com.genersoft.iot.vmp.media.zlm.dto.MediaSendRtpPortInfo;
  5 +import org.slf4j.Logger;
  6 +import org.slf4j.LoggerFactory;
  7 +import org.springframework.beans.factory.annotation.Autowired;
  8 +import org.springframework.data.redis.core.RedisTemplate;
  9 +import org.springframework.stereotype.Component;
  10 +
  11 +@Component
  12 +public class SendRtpPortManager {
  13 +
  14 + private final static Logger logger = LoggerFactory.getLogger(SendRtpPortManager.class);
  15 +
  16 + @Autowired
  17 + private UserSetting userSetting;
  18 +
  19 + @Autowired
  20 + private RedisTemplate<Object, Object> redisTemplate;
  21 +
  22 + private final String KEY = "VM_MEDIA_SEND_RTP_PORT_RANGE_";
  23 +
  24 +
  25 + public void initServerPort(String mediaServerId, int startPort, int endPort){
  26 + String key = KEY + userSetting.getServerId() + "_" + mediaServerId;
  27 + MediaSendRtpPortInfo mediaSendRtpPortInfo = new MediaSendRtpPortInfo(startPort, endPort, mediaServerId);
  28 + redisTemplate.opsForValue().set(key, mediaSendRtpPortInfo);
  29 + }
  30 +
  31 + public int getNextPort(String mediaServerId) {
  32 + String key = KEY + userSetting.getServerId() + "_" + mediaServerId;
  33 + MediaSendRtpPortInfo mediaSendRtpPortInfo = (MediaSendRtpPortInfo)redisTemplate.opsForValue().get(key);
  34 + if (mediaSendRtpPortInfo == null) {
  35 + logger.warn("[发送端口管理] 获取{}的发送端口时未找到端口信息", mediaSendRtpPortInfo);
  36 + return 0;
  37 + }
  38 + int port;
  39 + if (mediaSendRtpPortInfo.getCurrent() %2 != 0) {
  40 + port = mediaSendRtpPortInfo.getCurrent() + 1;
  41 + }else {
  42 + port = mediaSendRtpPortInfo.getCurrent() + 2;
  43 + }
  44 + if (port > mediaSendRtpPortInfo.getEnd()) {
  45 + if (mediaSendRtpPortInfo.getStart() %2 != 0) {
  46 + port = mediaSendRtpPortInfo.getStart() + 1;
  47 + }else {
  48 + port = mediaSendRtpPortInfo.getStart();
  49 + }
  50 + }
  51 + mediaSendRtpPortInfo.setCurrent(port);
  52 + redisTemplate.opsForValue().set(key, mediaSendRtpPortInfo);
  53 + return port;
  54 + }
  55 +}
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -23,7 +23,6 @@ import com.genersoft.iot.vmp.service.*; @@ -23,7 +23,6 @@ import com.genersoft.iot.vmp.service.*;
23 import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; 23 import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
24 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 24 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
25 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 25 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
26 -import com.genersoft.iot.vmp.utils.redis.RedisUtil;  
27 import com.genersoft.iot.vmp.vmanager.bean.*; 26 import com.genersoft.iot.vmp.vmanager.bean.*;
28 import org.slf4j.Logger; 27 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory; 28 import org.slf4j.LoggerFactory;
@@ -223,9 +222,6 @@ public class ZLMHttpHookListener { @@ -223,9 +222,6 @@ public class ZLMHttpHookListener {
223 222
224 223
225 HookResultForOnPublish result = HookResultForOnPublish.SUCCESS(); 224 HookResultForOnPublish result = HookResultForOnPublish.SUCCESS();
226 - if (!"rtp".equals(param.getApp())) {  
227 - result.setEnable_audio(true);  
228 - }  
229 225
230 taskExecutor.execute(() -> { 226 taskExecutor.execute(() -> {
231 ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_publish, json); 227 ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_publish, json);
@@ -259,20 +255,6 @@ public class ZLMHttpHookListener { @@ -259,20 +255,6 @@ public class ZLMHttpHookListener {
259 } 255 }
260 } 256 }
261 257
262 - String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "*";  
263 - // 将信息写入redis中,以备后用  
264 - List<Object> scan = RedisUtil.scan(redisTemplate, receiveKey);  
265 - if (scan.size()>0) {  
266 - for (Object o : scan) {  
267 - String key = (String) o;  
268 - OtherRtpSendInfo otherRtpSendInfo = (OtherRtpSendInfo)redisTemplate.opsForValue().get(key);  
269 - if (otherRtpSendInfo != null && otherRtpSendInfo.getStream().equalsIgnoreCase(param.getStream())) {  
270 - result.setEnable_audio(true);  
271 - result.setEnable_mp4(true);  
272 - }  
273 - }  
274 - }  
275 -  
276 if (mediaInfo.getRecordAssistPort() > 0 && userSetting.getRecordPath() == null) { 258 if (mediaInfo.getRecordAssistPort() > 0 && userSetting.getRecordPath() == null) {
277 logger.info("推流时发现尚未设置录像路径,从assist服务中读取"); 259 logger.info("推流时发现尚未设置录像路径,从assist服务中读取");
278 JSONObject info = assistRESTfulUtils.getInfo(mediaInfo, null); 260 JSONObject info = assistRESTfulUtils.getInfo(mediaInfo, null);
@@ -291,6 +273,18 @@ public class ZLMHttpHookListener { @@ -291,6 +273,18 @@ public class ZLMHttpHookListener {
291 } 273 }
292 } 274 }
293 } 275 }
  276 + if (param.getApp().equalsIgnoreCase("rtp")) {
  277 + String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_" + param.getStream();
  278 + System.out.println(receiveKey);
  279 + OtherRtpSendInfo otherRtpSendInfo = (OtherRtpSendInfo)redisTemplate.opsForValue().get(receiveKey);
  280 + System.out.println("otherRtpSendInfo != null ====>" + (otherRtpSendInfo != null));
  281 + if (otherRtpSendInfo != null) {
  282 + System.out.println("otherRtpSendInfo != null");
  283 + result.setEnable_audio(true);
  284 + result.setEnable_mp4(true);
  285 + }
  286 + }
  287 + logger.info("[ZLM HOOK]推流鉴权 响应:{}->{}->>>>{}", param.getMediaServerId(), param, result);
294 return result; 288 return result;
295 } 289 }
296 290
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
1 package com.genersoft.iot.vmp.media.zlm; 1 package com.genersoft.iot.vmp.media.zlm;
2 2
3 import com.alibaba.fastjson2.JSON; 3 import com.alibaba.fastjson2.JSON;
4 -import com.alibaba.fastjson2.JSONArray;  
5 import com.alibaba.fastjson2.JSONObject; 4 import com.alibaba.fastjson2.JSONObject;
6 import com.genersoft.iot.vmp.common.CommonCallback; 5 import com.genersoft.iot.vmp.common.CommonCallback;
7 import com.genersoft.iot.vmp.conf.UserSetting; 6 import com.genersoft.iot.vmp.conf.UserSetting;
8 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; 7 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
9 -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;  
10 -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForRtpServerTimeout;  
11 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 8 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
12 import org.slf4j.Logger; 9 import org.slf4j.Logger;
13 import org.slf4j.LoggerFactory; 10 import org.slf4j.LoggerFactory;
14 import org.springframework.beans.factory.annotation.Autowired; 11 import org.springframework.beans.factory.annotation.Autowired;
15 import org.springframework.stereotype.Component; 12 import org.springframework.stereotype.Component;
16 13
17 -import java.util.*; 14 +import java.util.HashMap;
  15 +import java.util.Map;
18 16
19 @Component 17 @Component
20 public class ZLMRTPServerFactory { 18 public class ZLMRTPServerFactory {
@@ -30,68 +28,8 @@ public class ZLMRTPServerFactory { @@ -30,68 +28,8 @@ public class ZLMRTPServerFactory {
30 @Autowired 28 @Autowired
31 private ZlmHttpHookSubscribe hookSubscribe; 29 private ZlmHttpHookSubscribe hookSubscribe;
32 30
33 - private int[] portRangeArray = new int[2];  
34 -  
35 - public int getFreePort(MediaServerItem mediaServerItem, int startPort, int endPort, List<Integer> usedFreelist) {  
36 - if (endPort <= startPort) {  
37 - return -1;  
38 - }  
39 - if (usedFreelist == null) {  
40 - usedFreelist = new ArrayList<>();  
41 - }  
42 - JSONObject listRtpServerJsonResult = zlmresTfulUtils.listRtpServer(mediaServerItem);  
43 - if (listRtpServerJsonResult != null) {  
44 - JSONArray data = listRtpServerJsonResult.getJSONArray("data");  
45 - if (data != null) {  
46 - for (int i = 0; i < data.size(); i++) {  
47 - JSONObject dataItem = data.getJSONObject(i);  
48 - usedFreelist.add(dataItem.getInteger("port"));  
49 - }  
50 - }  
51 - }  
52 -  
53 - Map<String, Object> param = new HashMap<>();  
54 - int result = -1;  
55 - // 设置推流端口  
56 - if (startPort%2 == 1) {  
57 - startPort ++;  
58 - }  
59 - boolean checkPort = false;  
60 - for (int i = startPort; i < endPort + 1; i+=2) {  
61 - if (!usedFreelist.contains(i)){  
62 - checkPort = true;  
63 - startPort = i;  
64 - break;  
65 - }  
66 - }  
67 - if (!checkPort) {  
68 - logger.warn("未找到节点{}上范围[{}-{}]的空闲端口", mediaServerItem.getId(), startPort, endPort);  
69 - return -1;  
70 - }  
71 - param.put("port", startPort);  
72 - String stream = UUID.randomUUID().toString();  
73 - param.put("enable_tcp", 1);  
74 - param.put("stream_id", stream);  
75 -// param.put("port", 0);  
76 - JSONObject openRtpServerResultJson = zlmresTfulUtils.openRtpServer(mediaServerItem, param);  
77 -  
78 - if (openRtpServerResultJson != null) {  
79 - if (openRtpServerResultJson.getInteger("code") == 0) {  
80 - result= openRtpServerResultJson.getInteger("port");  
81 - Map<String, Object> closeRtpServerParam = new HashMap<>();  
82 - closeRtpServerParam.put("stream_id", stream);  
83 - zlmresTfulUtils.closeRtpServer(mediaServerItem, closeRtpServerParam);  
84 - }else {  
85 - usedFreelist.add(startPort);  
86 - startPort +=2;  
87 - result = getFreePort(mediaServerItem, startPort, endPort,usedFreelist);  
88 - }  
89 - }else {  
90 - // 检查ZLM状态  
91 - logger.error("创建RTP Server 失败 {}: 请检查ZLM服务", param.get("port"));  
92 - }  
93 - return result;  
94 - } 31 + @Autowired
  32 + private SendRtpPortManager sendRtpPortManager;
95 33
96 /** 34 /**
97 * 开启rtpServer 35 * 开启rtpServer
@@ -220,13 +158,13 @@ public class ZLMRTPServerFactory { @@ -220,13 +158,13 @@ public class ZLMRTPServerFactory {
220 * @return SendRtpItem 158 * @return SendRtpItem
221 */ 159 */
222 public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, 160 public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId,
223 - String deviceId, String channelId, boolean tcp, boolean rtcp, KeepPortCallback callback){ 161 + String deviceId, String channelId, boolean tcp, boolean rtcp){
224 162
225 // 默认为随机端口 163 // 默认为随机端口
226 int localPort = 0; 164 int localPort = 0;
227 if (userSetting.getGbSendStreamStrict()) { 165 if (userSetting.getGbSendStreamStrict()) {
228 if (userSetting.getGbSendStreamStrict()) { 166 if (userSetting.getGbSendStreamStrict()) {
229 - localPort = keepPort(serverItem, ssrc, localPort, callback); 167 + localPort = sendRtpPortManager.getNextPort(serverItem.getId());
230 if (localPort == 0) { 168 if (localPort == 0) {
231 return null; 169 return null;
232 } 170 }
@@ -259,11 +197,11 @@ public class ZLMRTPServerFactory { @@ -259,11 +197,11 @@ public class ZLMRTPServerFactory {
259 * @return SendRtpItem 197 * @return SendRtpItem
260 */ 198 */
261 public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, 199 public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId,
262 - String app, String stream, String channelId, boolean tcp, boolean rtcp, KeepPortCallback callback){ 200 + String app, String stream, String channelId, boolean tcp, boolean rtcp){
263 // 默认为随机端口 201 // 默认为随机端口
264 int localPort = 0; 202 int localPort = 0;
265 if (userSetting.getGbSendStreamStrict()) { 203 if (userSetting.getGbSendStreamStrict()) {
266 - localPort = keepPort(serverItem, ssrc, localPort, callback); 204 + localPort = sendRtpPortManager.getNextPort(serverItem.getId());
267 if (localPort == 0) { 205 if (localPort == 0) {
268 return null; 206 return null;
269 } 207 }
@@ -284,58 +222,6 @@ public class ZLMRTPServerFactory { @@ -284,58 +222,6 @@ public class ZLMRTPServerFactory {
284 return sendRtpItem; 222 return sendRtpItem;
285 } 223 }
286 224
287 - public interface KeepPortCallback{  
288 - Boolean keep(String ssrc);  
289 - }  
290 -  
291 - /**  
292 - * 保持端口,直到需要需要发流时再释放  
293 - */  
294 - public int keepPort(MediaServerItem serverItem, String ssrc, int localPort, KeepPortCallback keepPortCallback) {  
295 - Map<String, Object> param = new HashMap<>(3);  
296 - param.put("port", localPort);  
297 - param.put("enable_tcp", 1);  
298 - param.put("stream_id", ssrc);  
299 - JSONObject jsonObject = zlmresTfulUtils.openRtpServer(serverItem, param);  
300 - if (jsonObject.getInteger("code") == 0) {  
301 - localPort = jsonObject.getInteger("port");  
302 - HookSubscribeForRtpServerTimeout hookSubscribeForRtpServerTimeout = HookSubscribeFactory.on_rtp_server_timeout(ssrc, null, serverItem.getId());  
303 - // 订阅 zlm启动事件, 新的zlm也会从这里进入系统  
304 - Integer finalLocalPort = localPort;  
305 - hookSubscribe.addSubscribe(hookSubscribeForRtpServerTimeout,  
306 - (MediaServerItem mediaServerItem, JSONObject response)->{  
307 - System.out.println("监听端口到期继续保持监听");  
308 - System.out.println(response);  
309 - if (ssrc.equals(response.getString("stream_id"))) {  
310 - if (keepPortCallback.keep(ssrc)) {  
311 - logger.info("[上级点播] {}->监听端口到期继续保持监听", ssrc);  
312 - keepPort(serverItem, ssrc, finalLocalPort, keepPortCallback);  
313 - }else {  
314 - logger.info("[上级点播] {}->发送取消,无需继续监听", ssrc);  
315 - releasePort(serverItem, ssrc);  
316 - }  
317 - }  
318 -  
319 - });  
320 - logger.info("[上级点播] {}->监听端口: {}", ssrc, localPort);  
321 - }else {  
322 - logger.info("[上级点播] 监听端口失败: {}", ssrc);  
323 - }  
324 - return localPort;  
325 - }  
326 -  
327 - /**  
328 - * 释放保持的端口  
329 - */  
330 - public boolean releasePort(MediaServerItem serverItem, String ssrc) {  
331 - logger.info("[上级点播] {}->释放监听端口", ssrc);  
332 - boolean closeRTPServerResult = closeRtpServer(serverItem, ssrc);  
333 - HookSubscribeForRtpServerTimeout hookSubscribeForRtpServerTimeout = HookSubscribeFactory.on_rtp_server_timeout(ssrc, null, serverItem.getId());  
334 - // 订阅 zlm启动事件, 新的zlm也会从这里进入系统  
335 - hookSubscribe.removeSubscribe(hookSubscribeForRtpServerTimeout);  
336 - return closeRTPServerResult;  
337 - }  
338 -  
339 /** 225 /**
340 * 调用zlm RESTFUL API —— startSendRtp 226 * 调用zlm RESTFUL API —— startSendRtp
341 */ 227 */
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaSendRtpPortInfo.java 0 → 100644
  1 +package com.genersoft.iot.vmp.media.zlm.dto;
  2 +
  3 +public class MediaSendRtpPortInfo {
  4 +
  5 + private int start;
  6 + private int end;
  7 + private String mediaServerId;
  8 +
  9 + private int current;
  10 +
  11 +
  12 + public MediaSendRtpPortInfo(int start, int end, String mediaServerId) {
  13 + this.start = start;
  14 + this.current = start;
  15 + this.end = end;
  16 + this.mediaServerId = mediaServerId;
  17 + }
  18 +
  19 + public int getStart() {
  20 + return start;
  21 + }
  22 +
  23 + public void setStart(int start) {
  24 + this.start = start;
  25 + }
  26 +
  27 + public int getEnd() {
  28 + return end;
  29 + }
  30 +
  31 + public void setEnd(int end) {
  32 + this.end = end;
  33 + }
  34 +
  35 + public String getMediaServerId() {
  36 + return mediaServerId;
  37 + }
  38 +
  39 + public void setMediaServerId(String mediaServerId) {
  40 + this.mediaServerId = mediaServerId;
  41 + }
  42 +
  43 + public int getCurrent() {
  44 + return current;
  45 + }
  46 +
  47 + public void setCurrent(int current) {
  48 + this.current = current;
  49 + }
  50 +}
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java
@@ -62,6 +62,9 @@ public class MediaServerItem{ @@ -62,6 +62,9 @@ public class MediaServerItem{
62 @Schema(description = "多端口RTP收流端口范围") 62 @Schema(description = "多端口RTP收流端口范围")
63 private String rtpPortRange; 63 private String rtpPortRange;
64 64
  65 + @Schema(description = "RTP发流端口范围")
  66 + private String sendRtpPortRange;
  67 +
65 @Schema(description = "assist服务端口") 68 @Schema(description = "assist服务端口")
66 private int recordAssistPort; 69 private int recordAssistPort;
67 70
@@ -297,4 +300,12 @@ public class MediaServerItem{ @@ -297,4 +300,12 @@ public class MediaServerItem{
297 public void setHookAliveInterval(Float hookAliveInterval) { 300 public void setHookAliveInterval(Float hookAliveInterval) {
298 this.hookAliveInterval = hookAliveInterval; 301 this.hookAliveInterval = hookAliveInterval;
299 } 302 }
  303 +
  304 + public String getSendRtpPortRange() {
  305 + return sendRtpPortRange;
  306 + }
  307 +
  308 + public void setSendRtpPortRange(String sendRtpPortRange) {
  309 + this.sendRtpPortRange = sendRtpPortRange;
  310 + }
300 } 311 }
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookResultForOnPublish.java
@@ -50,4 +50,14 @@ public class HookResultForOnPublish extends HookResult{ @@ -50,4 +50,14 @@ public class HookResultForOnPublish extends HookResult{
50 public void setMp4_save_path(String mp4_save_path) { 50 public void setMp4_save_path(String mp4_save_path) {
51 this.mp4_save_path = mp4_save_path; 51 this.mp4_save_path = mp4_save_path;
52 } 52 }
  53 +
  54 + @Override
  55 + public String toString() {
  56 + return "HookResultForOnPublish{" +
  57 + "enable_audio=" + enable_audio +
  58 + ", enable_mp4=" + enable_mp4 +
  59 + ", mp4_max_second=" + mp4_max_second +
  60 + ", mp4_save_path='" + mp4_save_path + '\'' +
  61 + '}';
  62 + }
53 } 63 }
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
@@ -11,10 +11,7 @@ import com.genersoft.iot.vmp.conf.UserSetting; @@ -11,10 +11,7 @@ import com.genersoft.iot.vmp.conf.UserSetting;
11 import com.genersoft.iot.vmp.conf.exception.ControllerException; 11 import com.genersoft.iot.vmp.conf.exception.ControllerException;
12 import com.genersoft.iot.vmp.gb28181.event.EventPublisher; 12 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
13 import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; 13 import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
14 -import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;  
15 -import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;  
16 -import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;  
17 -import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; 14 +import com.genersoft.iot.vmp.media.zlm.*;
18 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 15 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
19 import com.genersoft.iot.vmp.media.zlm.dto.ServerKeepaliveData; 16 import com.genersoft.iot.vmp.media.zlm.dto.ServerKeepaliveData;
20 import com.genersoft.iot.vmp.service.IMediaServerService; 17 import com.genersoft.iot.vmp.service.IMediaServerService;
@@ -70,6 +67,10 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -70,6 +67,10 @@ public class MediaServerServiceImpl implements IMediaServerService {
70 private UserSetting userSetting; 67 private UserSetting userSetting;
71 68
72 @Autowired 69 @Autowired
  70 + private SendRtpPortManager sendRtpPortManager;
  71 +
  72 +
  73 + @Autowired
73 private AssistRESTfulUtils assistRESTfulUtils; 74 private AssistRESTfulUtils assistRESTfulUtils;
74 75
75 @Autowired 76 @Autowired
@@ -115,13 +116,40 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -115,13 +116,40 @@ public class MediaServerServiceImpl implements IMediaServerService {
115 if (ssrcFactory.hasMediaServerSSRC(mediaServerItem.getId())) { 116 if (ssrcFactory.hasMediaServerSSRC(mediaServerItem.getId())) {
116 ssrcFactory.initMediaServerSSRC(mediaServerItem.getId(), null); 117 ssrcFactory.initMediaServerSSRC(mediaServerItem.getId(), null);
117 } 118 }
  119 + if (userSetting.getGbSendStreamStrict()) {
  120 + int startPort = 50000;
  121 + int endPort = 60000;
  122 + String sendRtpPortRange = mediaServerItem.getSendRtpPortRange();
  123 + if (sendRtpPortRange == null) {
  124 + logger.warn("[zlm] ] 未配置发流端口范围,默认使用50000到60000");
  125 + }else {
  126 + String[] sendRtpPortRangeArray = sendRtpPortRange.trim().split(",");
  127 + if (sendRtpPortRangeArray.length != 2) {
  128 + logger.warn("[zlm] ] 发流端口范围错误,默认使用50000到60000");
  129 + }else {
  130 + try {
  131 + startPort = Integer.parseInt(sendRtpPortRangeArray[0]);
  132 + endPort = Integer.parseInt(sendRtpPortRangeArray[1]);
  133 + if (endPort <= startPort) {
  134 + logger.warn("[zlm] ] 发流端口范围错误,结束端口应大于开始端口,使用默认端口");
  135 + startPort = 50000;
  136 + endPort = 60000;
  137 + }
  138 +
  139 + }catch (NumberFormatException e) {
  140 + logger.warn("[zlm] ] 发流端口范围错误,默认使用50000到60000");
  141 + }
  142 + }
  143 + }
  144 + logger.info("[[zlm] ] 配置发流端口范围,{}-{}", startPort, endPort);
  145 + sendRtpPortManager.initServerPort(mediaServerItem.getId(), startPort, endPort);
  146 + }
118 // 查询redis是否存在此mediaServer 147 // 查询redis是否存在此mediaServer
119 String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(); 148 String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId();
120 Boolean hasKey = redisTemplate.hasKey(key); 149 Boolean hasKey = redisTemplate.hasKey(key);
121 if (hasKey != null && ! hasKey) { 150 if (hasKey != null && ! hasKey) {
122 redisTemplate.opsForValue().set(key, mediaServerItem); 151 redisTemplate.opsForValue().set(key, mediaServerItem);
123 } 152 }
124 -  
125 } 153 }
126 } 154 }
127 155
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java
@@ -317,9 +317,7 @@ public class RedisGbPlayMsgListener implements MessageListener { @@ -317,9 +317,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
317 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, content.getIp(), 317 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, content.getIp(),
318 content.getPort(), content.getSsrc(), content.getPlatformId(), 318 content.getPort(), content.getSsrc(), content.getPlatformId(),
319 content.getApp(), content.getStream(), content.getChannelId(), 319 content.getApp(), content.getStream(), content.getChannelId(),
320 - content.getTcp(), content.getRtcp(), ssrcFromCallback -> {  
321 - return querySendRTPServer(content.getPlatformId(), content.getChannelId(), content.getStream(), null) != null;  
322 - }); 320 + content.getTcp(), content.getRtcp());
323 321
324 WVPResult<ResponseSendItemMsg> result = new WVPResult<>(); 322 WVPResult<ResponseSendItemMsg> result = new WVPResult<>();
325 result.setCode(0); 323 result.setCode(0);
src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java
@@ -28,6 +28,7 @@ public interface MediaServerMapper { @@ -28,6 +28,7 @@ public interface MediaServerMapper {
28 "secret, " + 28 "secret, " +
29 "rtpEnable, " + 29 "rtpEnable, " +
30 "rtpPortRange, " + 30 "rtpPortRange, " +
  31 + "sendRtpPortRange, " +
31 "recordAssistPort, " + 32 "recordAssistPort, " +
32 "defaultServer, " + 33 "defaultServer, " +
33 "createTime, " + 34 "createTime, " +
@@ -51,6 +52,7 @@ public interface MediaServerMapper { @@ -51,6 +52,7 @@ public interface MediaServerMapper {
51 "#{secret}, " + 52 "#{secret}, " +
52 "#{rtpEnable}, " + 53 "#{rtpEnable}, " +
53 "#{rtpPortRange}, " + 54 "#{rtpPortRange}, " +
  55 + "#{sendRtpPortRange}, " +
54 "#{recordAssistPort}, " + 56 "#{recordAssistPort}, " +
55 "#{defaultServer}, " + 57 "#{defaultServer}, " +
56 "#{createTime}, " + 58 "#{createTime}, " +
@@ -75,6 +77,7 @@ public interface MediaServerMapper { @@ -75,6 +77,7 @@ public interface MediaServerMapper {
75 "<if test=\"autoConfig != null\">, autoConfig=#{autoConfig}</if>" + 77 "<if test=\"autoConfig != null\">, autoConfig=#{autoConfig}</if>" +
76 "<if test=\"rtpEnable != null\">, rtpEnable=#{rtpEnable}</if>" + 78 "<if test=\"rtpEnable != null\">, rtpEnable=#{rtpEnable}</if>" +
77 "<if test=\"rtpPortRange != null\">, rtpPortRange=#{rtpPortRange}</if>" + 79 "<if test=\"rtpPortRange != null\">, rtpPortRange=#{rtpPortRange}</if>" +
  80 + "<if test=\"sendRtpPortRange != null\">, sendRtpPortRange=#{sendRtpPortRange}</if>" +
78 "<if test=\"secret != null\">, secret=#{secret}</if>" + 81 "<if test=\"secret != null\">, secret=#{secret}</if>" +
79 "<if test=\"recordAssistPort != null\">, recordAssistPort=#{recordAssistPort}</if>" + 82 "<if test=\"recordAssistPort != null\">, recordAssistPort=#{recordAssistPort}</if>" +
80 "<if test=\"hookAliveInterval != null\">, hookAliveInterval=#{hookAliveInterval}</if>" + 83 "<if test=\"hookAliveInterval != null\">, hookAliveInterval=#{hookAliveInterval}</if>" +
@@ -98,6 +101,7 @@ public interface MediaServerMapper { @@ -98,6 +101,7 @@ public interface MediaServerMapper {
98 "<if test=\"autoConfig != null\">, autoConfig=#{autoConfig}</if>" + 101 "<if test=\"autoConfig != null\">, autoConfig=#{autoConfig}</if>" +
99 "<if test=\"rtpEnable != null\">, rtpEnable=#{rtpEnable}</if>" + 102 "<if test=\"rtpEnable != null\">, rtpEnable=#{rtpEnable}</if>" +
100 "<if test=\"rtpPortRange != null\">, rtpPortRange=#{rtpPortRange}</if>" + 103 "<if test=\"rtpPortRange != null\">, rtpPortRange=#{rtpPortRange}</if>" +
  104 + "<if test=\"sendRtpPortRange != null\">, sendRtpPortRange=#{sendRtpPortRange}</if>" +
101 "<if test=\"secret != null\">, secret=#{secret}</if>" + 105 "<if test=\"secret != null\">, secret=#{secret}</if>" +
102 "<if test=\"recordAssistPort != null\">, recordAssistPort=#{recordAssistPort}</if>" + 106 "<if test=\"recordAssistPort != null\">, recordAssistPort=#{recordAssistPort}</if>" +
103 "<if test=\"hookAliveInterval != null\">, hookAliveInterval=#{hookAliveInterval}</if>" + 107 "<if test=\"hookAliveInterval != null\">, hookAliveInterval=#{hookAliveInterval}</if>" +
src/main/java/com/genersoft/iot/vmp/vmanager/bean/OtherRtpSendInfo.java
@@ -124,7 +124,7 @@ public class OtherRtpSendInfo { @@ -124,7 +124,7 @@ public class OtherRtpSendInfo {
124 @Override 124 @Override
125 public String toString() { 125 public String toString() {
126 return "OtherRtpSendInfo{" + 126 return "OtherRtpSendInfo{" +
127 - "ip='" + ip + '\'' + 127 + " ip='" + ip + '\'' +
128 ", port=" + port + 128 ", port=" + port +
129 ", receiveIp='" + receiveIp + '\'' + 129 ", receiveIp='" + receiveIp + '\'' +
130 ", receivePort=" + receivePort + 130 ", receivePort=" + receivePort +
src/main/java/com/genersoft/iot/vmp/vmanager/rtp/RtpController.java
@@ -3,20 +3,16 @@ package com.genersoft.iot.vmp.vmanager.rtp; @@ -3,20 +3,16 @@ package com.genersoft.iot.vmp.vmanager.rtp;
3 import com.alibaba.fastjson2.JSONObject; 3 import com.alibaba.fastjson2.JSONObject;
4 import com.genersoft.iot.vmp.common.VideoManagerConstants; 4 import com.genersoft.iot.vmp.common.VideoManagerConstants;
5 import com.genersoft.iot.vmp.conf.DynamicTask; 5 import com.genersoft.iot.vmp.conf.DynamicTask;
6 -import com.genersoft.iot.vmp.conf.SipConfig;  
7 import com.genersoft.iot.vmp.conf.UserSetting; 6 import com.genersoft.iot.vmp.conf.UserSetting;
8 -import com.genersoft.iot.vmp.conf.VersionInfo;  
9 import com.genersoft.iot.vmp.conf.exception.ControllerException; 7 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  8 +import com.genersoft.iot.vmp.media.zlm.SendRtpPortManager;
10 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; 9 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
11 import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; 10 import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
12 import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; 11 import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
13 import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForRtpServerTimeout; 12 import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForRtpServerTimeout;
14 import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; 13 import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
15 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 14 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
16 -import com.genersoft.iot.vmp.service.IDeviceChannelService;  
17 -import com.genersoft.iot.vmp.service.IDeviceService;  
18 import com.genersoft.iot.vmp.service.IMediaServerService; 15 import com.genersoft.iot.vmp.service.IMediaServerService;
19 -import com.genersoft.iot.vmp.storager.IRedisCatchStorage;  
20 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 16 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
21 import com.genersoft.iot.vmp.vmanager.bean.OtherRtpSendInfo; 17 import com.genersoft.iot.vmp.vmanager.bean.OtherRtpSendInfo;
22 import io.swagger.v3.oas.annotations.Operation; 18 import io.swagger.v3.oas.annotations.Operation;
@@ -27,7 +23,6 @@ import okhttp3.Request; @@ -27,7 +23,6 @@ import okhttp3.Request;
27 import org.slf4j.Logger; 23 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory; 24 import org.slf4j.LoggerFactory;
29 import org.springframework.beans.factory.annotation.Autowired; 25 import org.springframework.beans.factory.annotation.Autowired;
30 -import org.springframework.beans.factory.annotation.Value;  
31 import org.springframework.data.redis.core.RedisTemplate; 26 import org.springframework.data.redis.core.RedisTemplate;
32 import org.springframework.util.ObjectUtils; 27 import org.springframework.util.ObjectUtils;
33 import org.springframework.web.bind.annotation.*; 28 import org.springframework.web.bind.annotation.*;
@@ -36,6 +31,7 @@ import java.io.IOException; @@ -36,6 +31,7 @@ import java.io.IOException;
36 import java.util.HashMap; 31 import java.util.HashMap;
37 import java.util.Map; 32 import java.util.Map;
38 import java.util.UUID; 33 import java.util.UUID;
  34 +import java.util.concurrent.TimeUnit;
39 35
40 @SuppressWarnings("rawtypes") 36 @SuppressWarnings("rawtypes")
41 @Tag(name = "第三方服务对接") 37 @Tag(name = "第三方服务对接")
@@ -56,21 +52,12 @@ public class RtpController { @@ -56,21 +52,12 @@ public class RtpController {
56 private IMediaServerService mediaServerService; 52 private IMediaServerService mediaServerService;
57 53
58 @Autowired 54 @Autowired
59 - private VersionInfo versionInfo;  
60 -  
61 - @Autowired  
62 - private SipConfig sipConfig; 55 + private SendRtpPortManager sendRtpPortManager;
63 56
64 @Autowired 57 @Autowired
65 private UserSetting userSetting; 58 private UserSetting userSetting;
66 59
67 @Autowired 60 @Autowired
68 - private IDeviceService deviceService;  
69 -  
70 - @Autowired  
71 - private IDeviceChannelService channelService;  
72 -  
73 - @Autowired  
74 private DynamicTask dynamicTask; 61 private DynamicTask dynamicTask;
75 62
76 63
@@ -78,14 +65,6 @@ public class RtpController { @@ -78,14 +65,6 @@ public class RtpController {
78 private RedisTemplate<Object, Object> redisTemplate; 65 private RedisTemplate<Object, Object> redisTemplate;
79 66
80 67
81 - @Value("${server.port}")  
82 - private int serverPort;  
83 -  
84 -  
85 - @Autowired  
86 - private IRedisCatchStorage redisCatchStorage;  
87 -  
88 -  
89 @GetMapping(value = "/receive/open") 68 @GetMapping(value = "/receive/open")
90 @ResponseBody 69 @ResponseBody
91 @Operation(summary = "开启收流和获取发流信息") 70 @Operation(summary = "开启收流和获取发流信息")
@@ -145,24 +124,15 @@ public class RtpController { @@ -145,24 +124,15 @@ public class RtpController {
145 otherRtpSendInfo.setReceivePort(localPort); 124 otherRtpSendInfo.setReceivePort(localPort);
146 otherRtpSendInfo.setCallId(callId); 125 otherRtpSendInfo.setCallId(callId);
147 otherRtpSendInfo.setStream(stream); 126 otherRtpSendInfo.setStream(stream);
148 - String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + stream; 127 + String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_" + stream;
149 // 将信息写入redis中,以备后用 128 // 将信息写入redis中,以备后用
150 redisTemplate.opsForValue().set(receiveKey, otherRtpSendInfo); 129 redisTemplate.opsForValue().set(receiveKey, otherRtpSendInfo);
151 if (isSend != null && isSend) { 130 if (isSend != null && isSend) {
152 - String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + callId; 131 + String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + "_" + callId;
153 // 预创建发流信息 132 // 预创建发流信息
154 - int port = zlmServerFactory.keepPort(mediaServerItem, callId, 0, ssrc1 -> {  
155 - return redisTemplate.opsForValue().get(key) != null;  
156 - });  
157 - 133 + int port = sendRtpPortManager.getNextPort(mediaServerItem.getId());
158 // 将信息写入redis中,以备后用 134 // 将信息写入redis中,以备后用
159 - redisTemplate.opsForValue().set(key, otherRtpSendInfo);  
160 - // 设置超时任务,超时未使用,则自动移除,并关闭端口保持, 默认五分钟  
161 - dynamicTask.startDelay(key, ()->{  
162 - logger.info("[第三方服务对接->开启收流和获取发流信息] 端口保持超时 callId->{}", callId);  
163 - redisTemplate.delete(key);  
164 - zlmServerFactory.releasePort(mediaServerItem, callId);  
165 - }, 15000); 135 + redisTemplate.opsForValue().set(key, otherRtpSendInfo, 300, TimeUnit.SECONDS);
166 otherRtpSendInfo.setIp(mediaServerItem.getSdpIp()); 136 otherRtpSendInfo.setIp(mediaServerItem.getSdpIp());
167 otherRtpSendInfo.setPort(port); 137 otherRtpSendInfo.setPort(port);
168 logger.info("[第三方服务对接->开启收流和获取发流信息] 结果,callId->{}, {}", callId, otherRtpSendInfo); 138 logger.info("[第三方服务对接->开启收流和获取发流信息] 结果,callId->{}, {}", callId, otherRtpSendInfo);
@@ -178,7 +148,7 @@ public class RtpController { @@ -178,7 +148,7 @@ public class RtpController {
178 logger.info("[第三方服务对接->关闭收流] stream->{}", stream); 148 logger.info("[第三方服务对接->关闭收流] stream->{}", stream);
179 MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer(); 149 MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer();
180 zlmServerFactory.closeRtpServer(mediaServerItem,stream); 150 zlmServerFactory.closeRtpServer(mediaServerItem,stream);
181 - String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + stream; 151 + String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_" + stream;
182 // 将信息写入redis中,以备后用 152 // 将信息写入redis中,以备后用
183 redisTemplate.delete(receiveKey); 153 redisTemplate.delete(receiveKey);
184 } 154 }
@@ -203,11 +173,9 @@ public class RtpController { @@ -203,11 +173,9 @@ public class RtpController {
203 streamType = 1; 173 streamType = 1;
204 } 174 }
205 MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer(); 175 MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer();
206 - String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + callId; 176 + String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + "_" + callId;
207 OtherRtpSendInfo sendInfo = (OtherRtpSendInfo)redisTemplate.opsForValue().get(key); 177 OtherRtpSendInfo sendInfo = (OtherRtpSendInfo)redisTemplate.opsForValue().get(key);
208 - if (sendInfo != null) {  
209 - zlmServerFactory.releasePort(mediaServerItem, callId);  
210 - }else { 178 + if (sendInfo == null) {
211 sendInfo = new OtherRtpSendInfo(); 179 sendInfo = new OtherRtpSendInfo();
212 } 180 }
213 sendInfo.setPushApp(app); 181 sendInfo.setPushApp(app);
@@ -229,7 +197,6 @@ public class RtpController { @@ -229,7 +197,6 @@ public class RtpController {
229 param.put("only_audio", onlyAudio ? "1" : "0"); 197 param.put("only_audio", onlyAudio ? "1" : "0");
230 param.put("pt", pt); 198 param.put("pt", pt);
231 199
232 - dynamicTask.stop(key);  
233 Boolean streamReady = zlmServerFactory.isStreamReady(mediaServerItem, app, stream); 200 Boolean streamReady = zlmServerFactory.isStreamReady(mediaServerItem, app, stream);
234 if (streamReady) { 201 if (streamReady) {
235 logger.info("[第三方服务对接->发送流] 流存在,开始发流,callId->{}", callId); 202 logger.info("[第三方服务对接->发送流] 流存在,开始发流,callId->{}", callId);
@@ -279,7 +246,7 @@ public class RtpController { @@ -279,7 +246,7 @@ public class RtpController {
279 @Parameter(name = "callId", description = "整个过程的唯一标识,不传则使用随机端口发流", required = true) 246 @Parameter(name = "callId", description = "整个过程的唯一标识,不传则使用随机端口发流", required = true)
280 public void closeSendRTP(String callId) { 247 public void closeSendRTP(String callId) {
281 logger.info("[第三方服务对接->关闭发送流] callId->{}", callId); 248 logger.info("[第三方服务对接->关闭发送流] callId->{}", callId);
282 - String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + callId; 249 + String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + "_" + callId;
283 OtherRtpSendInfo sendInfo = (OtherRtpSendInfo)redisTemplate.opsForValue().get(key); 250 OtherRtpSendInfo sendInfo = (OtherRtpSendInfo)redisTemplate.opsForValue().get(key);
284 if (sendInfo == null){ 251 if (sendInfo == null){
285 throw new ControllerException(ErrorCode.ERROR100.getCode(), "未开启发流"); 252 throw new ControllerException(ErrorCode.ERROR100.getCode(), "未开启发流");
web_src/src/components/dialog/MediaServerEdit.vue
@@ -89,6 +89,11 @@ @@ -89,6 +89,11 @@
89 - 89 -
90 <el-input v-model="rtpPortRange2" placeholder="终止" @change="portRangeChange" clearable style="width: 100px" prop="rtpPortRange2" :disabled="mediaServerForm.defaultServer"></el-input> 90 <el-input v-model="rtpPortRange2" placeholder="终止" @change="portRangeChange" clearable style="width: 100px" prop="rtpPortRange2" :disabled="mediaServerForm.defaultServer"></el-input>
91 </el-form-item> 91 </el-form-item>
  92 + <el-form-item v-if="mediaServerForm.sendRtpEnable" label="发流端口" >
  93 + <el-input v-model="sendRtpPortRange1" placeholder="起始" @change="portRangeChange" clearable style="width: 100px" prop="rtpPortRange1" :disabled="mediaServerForm.defaultServer"></el-input>
  94 + -
  95 + <el-input v-model="sendRtpPortRange2" placeholder="终止" @change="portRangeChange" clearable style="width: 100px" prop="rtpPortRange2" :disabled="mediaServerForm.defaultServer"></el-input>
  96 + </el-form-item>
92 <el-form-item label="录像管理服务端口" prop="recordAssistPort"> 97 <el-form-item label="录像管理服务端口" prop="recordAssistPort">
93 <el-input v-model.number="mediaServerForm.recordAssistPort" :disabled="mediaServerForm.defaultServer"> 98 <el-input v-model.number="mediaServerForm.recordAssistPort" :disabled="mediaServerForm.defaultServer">
94 <!-- <el-button v-if="mediaServerForm.recordAssistPort > 0" slot="append" type="primary" @click="checkRecordServer">测试</el-button>--> 99 <!-- <el-button v-if="mediaServerForm.recordAssistPort > 0" slot="append" type="primary" @click="checkRecordServer">测试</el-button>-->
@@ -172,6 +177,7 @@ export default { @@ -172,6 +177,7 @@ export default {
172 rtmpSSlPort: "", 177 rtmpSSlPort: "",
173 rtpEnable: false, 178 rtpEnable: false,
174 rtpPortRange: "", 179 rtpPortRange: "",
  180 + sendRtpPortRange: "",
175 rtpProxyPort: "", 181 rtpProxyPort: "",
176 rtspPort: "", 182 rtspPort: "",
177 rtspSSLPort: "", 183 rtspSSLPort: "",
@@ -179,6 +185,9 @@ export default { @@ -179,6 +185,9 @@ export default {
179 rtpPortRange1:30000, 185 rtpPortRange1:30000,
180 rtpPortRange2:30500, 186 rtpPortRange2:30500,
181 187
  188 + sendRtpPortRange1:50000,
  189 + sendRtpPortRange2:60000,
  190 +
182 rules: { 191 rules: {
183 ip: [{ required: true, validator: isValidIp, message: '请输入有效的IP地址', trigger: 'blur' }], 192 ip: [{ required: true, validator: isValidIp, message: '请输入有效的IP地址', trigger: 'blur' }],
184 httpPort: [{ required: true, validator: isValidPort, message: '请输入有效的端口号', trigger: 'blur' }], 193 httpPort: [{ required: true, validator: isValidPort, message: '请输入有效的端口号', trigger: 'blur' }],
@@ -214,10 +223,15 @@ export default { @@ -214,10 +223,15 @@ export default {
214 this.currentStep = 3; 223 this.currentStep = 3;
215 if (param.rtpPortRange) { 224 if (param.rtpPortRange) {
216 let rtpPortRange = this.mediaServerForm.rtpPortRange.split(","); 225 let rtpPortRange = this.mediaServerForm.rtpPortRange.split(",");
  226 + let sendRtpPortRange = this.mediaServerForm.sendRtpPortRange.split(",");
217 if (rtpPortRange.length > 0) { 227 if (rtpPortRange.length > 0) {
218 this.rtpPortRange1 = rtpPortRange[0] 228 this.rtpPortRange1 = rtpPortRange[0]
219 this.rtpPortRange2 = rtpPortRange[1] 229 this.rtpPortRange2 = rtpPortRange[1]
220 } 230 }
  231 + if (sendRtpPortRange.length > 0) {
  232 + this.sendRtpPortRange1 = sendRtpPortRange[0]
  233 + this.sendRtpPortRange2 = sendRtpPortRange[1]
  234 + }
221 } 235 }
222 } 236 }
223 }, 237 },
@@ -240,6 +254,8 @@ export default { @@ -240,6 +254,8 @@ export default {
240 that.mediaServerForm.autoConfig = true; 254 that.mediaServerForm.autoConfig = true;
241 that.rtpPortRange1 = 30000 255 that.rtpPortRange1 = 30000
242 that.rtpPortRange2 = 30500 256 that.rtpPortRange2 = 30500
  257 + that.sendRtpPortRange1 = 50000
  258 + that.sendRtpPortRange2 = 60000
243 that.serverCheck = 1; 259 that.serverCheck = 1;
244 }else { 260 }else {
245 that.serverCheck = -1; 261 that.serverCheck = -1;
@@ -321,12 +337,15 @@ export default { @@ -321,12 +337,15 @@ export default {
321 rtmpSSlPort: "", 337 rtmpSSlPort: "",
322 rtpEnable: false, 338 rtpEnable: false,
323 rtpPortRange: "", 339 rtpPortRange: "",
  340 + sendRtpPortRange: "",
324 rtpProxyPort: "", 341 rtpProxyPort: "",
325 rtspPort: "", 342 rtspPort: "",
326 rtspSSLPort: "", 343 rtspSSLPort: "",
327 }; 344 };
328 this.rtpPortRange1 = 30500; 345 this.rtpPortRange1 = 30500;
329 this.rtpPortRange2 = 30500; 346 this.rtpPortRange2 = 30500;
  347 + this.sendRtpPortRange1 = 50000;
  348 + this.sendRtpPortRange2 = 60000;
330 this.listChangeCallback = null 349 this.listChangeCallback = null
331 this.currentStep = 1; 350 this.currentStep = 1;
332 }, 351 },
@@ -351,7 +370,7 @@ export default { @@ -351,7 +370,7 @@ export default {
351 portRangeChange: function() { 370 portRangeChange: function() {
352 if (this.mediaServerForm.rtpEnable) { 371 if (this.mediaServerForm.rtpEnable) {
353 this.mediaServerForm.rtpPortRange = this.rtpPortRange1 + "," + this.rtpPortRange2 372 this.mediaServerForm.rtpPortRange = this.rtpPortRange1 + "," + this.rtpPortRange2
354 - console.log(this.mediaServerForm.rtpPortRange) 373 + this.mediaServerForm.sendRtpPortRange = this.sendRtpPortRange1 + "," + this.sendRtpPortRange2
355 } 374 }
356 } 375 }
357 }, 376 },