Commit b64f32080537840cfd772d14dfc1df1ccddc4330
1 parent
c9164330
优化发流逻辑
Showing
15 changed files
with
222 additions
and
169 deletions
sql/2.6.8升级2.6.9.sql
| ... | ... | @@ -205,6 +205,12 @@ alter table media_server |
| 205 | 205 | change hookIp hook_ip varchar(50) not null; |
| 206 | 206 | |
| 207 | 207 | alter table media_server |
| 208 | + add send_rtp_port_range varchar(50) not null; | |
| 209 | + | |
| 210 | +alter table media_server | |
| 211 | + add column send_rtp_port_range varchar(50) default null; | |
| 212 | + | |
| 213 | +alter table media_server | |
| 208 | 214 | change sdpIp sdp_ip varchar(50) not null; |
| 209 | 215 | |
| 210 | 216 | alter table media_server | ... | ... |
sql/初始化.sql
| ... | ... | @@ -153,6 +153,7 @@ create table wvp_media_server ( |
| 153 | 153 | secret character varying(50), |
| 154 | 154 | rtp_enable bool default false, |
| 155 | 155 | rtp_port_range character varying(50), |
| 156 | + send_rtp_port_range character varying(50), | |
| 156 | 157 | record_assist_port integer, |
| 157 | 158 | default_server bool default false, |
| 158 | 159 | create_time character varying(50), | ... | ... |
src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java
| ... | ... | @@ -75,6 +75,9 @@ public class MediaConfig{ |
| 75 | 75 | @Value("${media.rtp.port-range}") |
| 76 | 76 | private String rtpPortRange; |
| 77 | 77 | |
| 78 | + @Value("${media.rtp.send-port-range}") | |
| 79 | + private String rtpSendPortRange; | |
| 80 | + | |
| 78 | 81 | @Value("${media.record-assist-port:0}") |
| 79 | 82 | private Integer recordAssistPort = 0; |
| 80 | 83 | |
| ... | ... | @@ -206,6 +209,7 @@ public class MediaConfig{ |
| 206 | 209 | mediaServerItem.setSecret(secret); |
| 207 | 210 | mediaServerItem.setRtpEnable(rtpEnable); |
| 208 | 211 | mediaServerItem.setRtpPortRange(rtpPortRange); |
| 212 | + mediaServerItem.setSendRtpPortRange(rtpSendPortRange); | |
| 209 | 213 | mediaServerItem.setRecordAssistPort(recordAssistPort); |
| 210 | 214 | mediaServerItem.setHookAliveInterval(30.00f); |
| 211 | 215 | |
| ... | ... | @@ -215,6 +219,14 @@ public class MediaConfig{ |
| 215 | 219 | return mediaServerItem; |
| 216 | 220 | } |
| 217 | 221 | |
| 222 | + public String getRtpSendPortRange() { | |
| 223 | + return rtpSendPortRange; | |
| 224 | + } | |
| 225 | + | |
| 226 | + public void setRtpSendPortRange(String rtpSendPortRange) { | |
| 227 | + this.rtpSendPortRange = rtpSendPortRange; | |
| 228 | + } | |
| 229 | + | |
| 218 | 230 | private boolean isValidIPAddress(String ipAddress) { |
| 219 | 231 | if ((ipAddress != null) && (!ipAddress.isEmpty())) { |
| 220 | 232 | return Pattern.matches("^([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}$", ipAddress); | ... | ... |
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 | 140 | startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, jsonObject, param, callIdHeader); |
| 141 | 141 | }); |
| 142 | 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 | 144 | if (startSendRtpStreamResult != null) { |
| 153 | 145 | startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, startSendRtpStreamResult, param, callIdHeader); |
| 154 | 146 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
| ... | ... | @@ -151,8 +151,6 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In |
| 151 | 151 | // 可能是设备发送的停止 |
| 152 | 152 | SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(null, null, callIdHeader.getCallId(), null); |
| 153 | 153 | if (ssrcTransaction == null) { |
| 154 | - logger.info("[收到bye] 但是无法获取推流信息和发流信息,忽略此请求"); | |
| 155 | - logger.info(request.toString()); | |
| 156 | 154 | return; |
| 157 | 155 | } |
| 158 | 156 | logger.info("[收到bye] 来自设备:{}, 通道已停止推流: {}", ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId()); | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
| ... | ... | @@ -346,9 +346,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 346 | 346 | } |
| 347 | 347 | logger.info("[上级Invite] {}, 平台:{}, 通道:{}, 收流地址:{}:{},收流方式:{}, ssrc:{}", sessionName, username, channelId, addressStr, port, streamTypeStr, ssrc); |
| 348 | 348 | SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, |
| 349 | - device.getDeviceId(), channelId, mediaTransmissionTCP, platform.isRtcp(), ssrcFromCallback -> { | |
| 350 | - return redisCatchStorage.querySendRTPServer(platform.getServerGBId(), channelId, null, callIdHeader.getCallId()) != null; | |
| 351 | - }); | |
| 349 | + device.getDeviceId(), channelId, mediaTransmissionTCP, platform.isRtcp()); | |
| 352 | 350 | |
| 353 | 351 | if (tcpActive != null) { |
| 354 | 352 | sendRtpItem.setTcpActive(tcpActive); |
| ... | ... | @@ -554,9 +552,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 554 | 552 | if (streamReady != null && streamReady) { |
| 555 | 553 | // 自平台内容 |
| 556 | 554 | SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, |
| 557 | - gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp(), ssrcFromCallback ->{ | |
| 558 | - return redisCatchStorage.querySendRTPServer(platform.getServerGBId(), channelId, null, callIdHeader.getCallId()) != null; | |
| 559 | - }); | |
| 555 | + gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp()); | |
| 560 | 556 | |
| 561 | 557 | if (sendRtpItem == null) { |
| 562 | 558 | logger.warn("服务器端口资源不足"); |
| ... | ... | @@ -595,9 +591,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 595 | 591 | if (streamReady != null && streamReady) { |
| 596 | 592 | // 自平台内容 |
| 597 | 593 | SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, |
| 598 | - gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp(), ssrcFromCallback ->{ | |
| 599 | - return redisCatchStorage.querySendRTPServer(platform.getServerGBId(), channelId, null, callIdHeader.getCallId()) != null; | |
| 600 | - }); | |
| 594 | + gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp()); | |
| 601 | 595 | |
| 602 | 596 | if (sendRtpItem == null) { |
| 603 | 597 | logger.warn("服务器端口资源不足"); |
| ... | ... | @@ -713,9 +707,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 713 | 707 | dynamicTask.stop(callIdHeader.getCallId()); |
| 714 | 708 | if (serverId.equals(userSetting.getServerId())) { |
| 715 | 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 | 712 | if (sendRtpItem == null) { |
| 721 | 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/ZLMRTPServerFactory.java
| 1 | 1 | package com.genersoft.iot.vmp.media.zlm; |
| 2 | 2 | |
| 3 | 3 | import com.alibaba.fastjson2.JSON; |
| 4 | -import com.alibaba.fastjson2.JSONArray; | |
| 5 | 4 | import com.alibaba.fastjson2.JSONObject; |
| 6 | 5 | import com.genersoft.iot.vmp.common.CommonCallback; |
| 7 | 6 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 8 | 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 | 8 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 12 | -import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam; | |
| 13 | -import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRtpServerTimeoutHookParam; | |
| 14 | 9 | import org.slf4j.Logger; |
| 15 | 10 | import org.slf4j.LoggerFactory; |
| 16 | 11 | import org.springframework.beans.factory.annotation.Autowired; |
| 17 | 12 | import org.springframework.stereotype.Component; |
| 18 | 13 | |
| 19 | -import java.util.*; | |
| 14 | +import java.util.HashMap; | |
| 15 | +import java.util.Map; | |
| 20 | 16 | |
| 21 | 17 | @Component |
| 22 | 18 | public class ZLMRTPServerFactory { |
| ... | ... | @@ -32,68 +28,9 @@ public class ZLMRTPServerFactory { |
| 32 | 28 | @Autowired |
| 33 | 29 | private ZlmHttpHookSubscribe hookSubscribe; |
| 34 | 30 | |
| 35 | - private int[] portRangeArray = new int[2]; | |
| 31 | + @Autowired | |
| 32 | + private SendRtpPortManager sendRtpPortManager; | |
| 36 | 33 | |
| 37 | - public int getFreePort(MediaServerItem mediaServerItem, int startPort, int endPort, List<Integer> usedFreelist) { | |
| 38 | - if (endPort <= startPort) { | |
| 39 | - return -1; | |
| 40 | - } | |
| 41 | - if (usedFreelist == null) { | |
| 42 | - usedFreelist = new ArrayList<>(); | |
| 43 | - } | |
| 44 | - JSONObject listRtpServerJsonResult = zlmresTfulUtils.listRtpServer(mediaServerItem); | |
| 45 | - if (listRtpServerJsonResult != null) { | |
| 46 | - JSONArray data = listRtpServerJsonResult.getJSONArray("data"); | |
| 47 | - if (data != null) { | |
| 48 | - for (int i = 0; i < data.size(); i++) { | |
| 49 | - JSONObject dataItem = data.getJSONObject(i); | |
| 50 | - usedFreelist.add(dataItem.getInteger("port")); | |
| 51 | - } | |
| 52 | - } | |
| 53 | - } | |
| 54 | - | |
| 55 | - Map<String, Object> param = new HashMap<>(); | |
| 56 | - int result = -1; | |
| 57 | - // 设置推流端口 | |
| 58 | - if (startPort%2 == 1) { | |
| 59 | - startPort ++; | |
| 60 | - } | |
| 61 | - boolean checkPort = false; | |
| 62 | - for (int i = startPort; i < endPort + 1; i+=2) { | |
| 63 | - if (!usedFreelist.contains(i)){ | |
| 64 | - checkPort = true; | |
| 65 | - startPort = i; | |
| 66 | - break; | |
| 67 | - } | |
| 68 | - } | |
| 69 | - if (!checkPort) { | |
| 70 | - logger.warn("未找到节点{}上范围[{}-{}]的空闲端口", mediaServerItem.getId(), startPort, endPort); | |
| 71 | - return -1; | |
| 72 | - } | |
| 73 | - param.put("port", startPort); | |
| 74 | - String stream = UUID.randomUUID().toString(); | |
| 75 | - param.put("enable_tcp", 1); | |
| 76 | - param.put("stream_id", stream); | |
| 77 | -// param.put("port", 0); | |
| 78 | - JSONObject openRtpServerResultJson = zlmresTfulUtils.openRtpServer(mediaServerItem, param); | |
| 79 | - | |
| 80 | - if (openRtpServerResultJson != null) { | |
| 81 | - if (openRtpServerResultJson.getInteger("code") == 0) { | |
| 82 | - result= openRtpServerResultJson.getInteger("port"); | |
| 83 | - Map<String, Object> closeRtpServerParam = new HashMap<>(); | |
| 84 | - closeRtpServerParam.put("stream_id", stream); | |
| 85 | - zlmresTfulUtils.closeRtpServer(mediaServerItem, closeRtpServerParam); | |
| 86 | - }else { | |
| 87 | - usedFreelist.add(startPort); | |
| 88 | - startPort +=2; | |
| 89 | - result = getFreePort(mediaServerItem, startPort, endPort,usedFreelist); | |
| 90 | - } | |
| 91 | - }else { | |
| 92 | - // 检查ZLM状态 | |
| 93 | - logger.error("创建RTP Server 失败 {}: 请检查ZLM服务", param.get("port")); | |
| 94 | - } | |
| 95 | - return result; | |
| 96 | - } | |
| 97 | 34 | |
| 98 | 35 | /** |
| 99 | 36 | * 开启rtpServer |
| ... | ... | @@ -222,16 +159,14 @@ public class ZLMRTPServerFactory { |
| 222 | 159 | * @return SendRtpItem |
| 223 | 160 | */ |
| 224 | 161 | public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, |
| 225 | - String deviceId, String channelId, boolean tcp, boolean rtcp, KeepPortCallback callback){ | |
| 162 | + String deviceId, String channelId, boolean tcp, boolean rtcp){ | |
| 226 | 163 | |
| 227 | 164 | // 默认为随机端口 |
| 228 | 165 | int localPort = 0; |
| 229 | 166 | if (userSetting.getGbSendStreamStrict()) { |
| 230 | - if (userSetting.getGbSendStreamStrict()) { | |
| 231 | - localPort = keepPort(serverItem, ssrc, localPort, callback); | |
| 232 | - if (localPort == 0) { | |
| 233 | - return null; | |
| 234 | - } | |
| 167 | + localPort = sendRtpPortManager.getNextPort(serverItem.getId()); | |
| 168 | + if (localPort == 0) { | |
| 169 | + return null; | |
| 235 | 170 | } |
| 236 | 171 | } |
| 237 | 172 | SendRtpItem sendRtpItem = new SendRtpItem(); |
| ... | ... | @@ -261,11 +196,11 @@ public class ZLMRTPServerFactory { |
| 261 | 196 | * @return SendRtpItem |
| 262 | 197 | */ |
| 263 | 198 | public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, |
| 264 | - String app, String stream, String channelId, boolean tcp, boolean rtcp, KeepPortCallback callback){ | |
| 199 | + String app, String stream, String channelId, boolean tcp, boolean rtcp){ | |
| 265 | 200 | // 默认为随机端口 |
| 266 | 201 | int localPort = 0; |
| 267 | 202 | if (userSetting.getGbSendStreamStrict()) { |
| 268 | - localPort = keepPort(serverItem, ssrc, localPort, callback); | |
| 203 | + localPort = sendRtpPortManager.getNextPort(serverItem.getId()); | |
| 269 | 204 | if (localPort == 0) { |
| 270 | 205 | return null; |
| 271 | 206 | } |
| ... | ... | @@ -286,58 +221,6 @@ public class ZLMRTPServerFactory { |
| 286 | 221 | return sendRtpItem; |
| 287 | 222 | } |
| 288 | 223 | |
| 289 | - public interface KeepPortCallback{ | |
| 290 | - Boolean keep(String ssrc); | |
| 291 | - } | |
| 292 | - | |
| 293 | - /** | |
| 294 | - * 保持端口,直到需要需要发流时再释放 | |
| 295 | - */ | |
| 296 | - public int keepPort(MediaServerItem serverItem, String ssrc, int localPort, KeepPortCallback keepPortCallback) { | |
| 297 | - Map<String, Object> param = new HashMap<>(3); | |
| 298 | - param.put("port", localPort); | |
| 299 | - param.put("enable_tcp", 1); | |
| 300 | - param.put("stream_id", ssrc); | |
| 301 | - JSONObject jsonObject = zlmresTfulUtils.openRtpServer(serverItem, param); | |
| 302 | - if (jsonObject.getInteger("code") == 0) { | |
| 303 | - localPort = jsonObject.getInteger("port"); | |
| 304 | - HookSubscribeForRtpServerTimeout hookSubscribeForRtpServerTimeout = HookSubscribeFactory.on_rtp_server_timeout(ssrc, null, serverItem.getId()); | |
| 305 | - // 订阅 zlm启动事件, 新的zlm也会从这里进入系统 | |
| 306 | - Integer finalLocalPort = localPort; | |
| 307 | - hookSubscribe.addSubscribe(hookSubscribeForRtpServerTimeout, | |
| 308 | - (MediaServerItem mediaServerItem, HookParam hookParam)->{ | |
| 309 | - logger.info("[上级点播] {}->监听端口到期继续保持监听: {}", ssrc, finalLocalPort); | |
| 310 | - OnRtpServerTimeoutHookParam rtpServerTimeoutHookParam = (OnRtpServerTimeoutHookParam) hookParam; | |
| 311 | - if (ssrc.equals(rtpServerTimeoutHookParam.getSsrc())) { | |
| 312 | - if (keepPortCallback.keep(ssrc)) { | |
| 313 | - logger.info("[上级点播] {}->监听端口到期继续保持监听", ssrc); | |
| 314 | - keepPort(serverItem, ssrc, finalLocalPort, keepPortCallback); | |
| 315 | - }else { | |
| 316 | - logger.info("[上级点播] {}->发送取消,无需继续监听", ssrc); | |
| 317 | - releasePort(serverItem, ssrc); | |
| 318 | - } | |
| 319 | - } | |
| 320 | - }); | |
| 321 | - logger.info("[上级点播] {}->监听端口: {}", ssrc, localPort); | |
| 322 | - return localPort; | |
| 323 | - }else { | |
| 324 | - logger.info("[上级点播] 监听端口失败: {}->{}", ssrc, localPort); | |
| 325 | - return 0; | |
| 326 | - } | |
| 327 | - } | |
| 328 | - | |
| 329 | - /** | |
| 330 | - * 释放保持的端口 | |
| 331 | - */ | |
| 332 | - public boolean releasePort(MediaServerItem serverItem, String ssrc) { | |
| 333 | - logger.info("[上级点播] {}->释放监听端口", ssrc); | |
| 334 | - boolean closeRTPServerResult = closeRtpServer(serverItem, ssrc); | |
| 335 | - HookSubscribeForRtpServerTimeout hookSubscribeForRtpServerTimeout = HookSubscribeFactory.on_rtp_server_timeout(ssrc, null, serverItem.getId()); | |
| 336 | - // 订阅 zlm启动事件, 新的zlm也会从这里进入系统 | |
| 337 | - hookSubscribe.removeSubscribe(hookSubscribeForRtpServerTimeout); | |
| 338 | - return closeRTPServerResult; | |
| 339 | - } | |
| 340 | - | |
| 341 | 224 | /** |
| 342 | 225 | * 调用zlm RESTFUL API —— startSendRtp |
| 343 | 226 | */ | ... | ... |
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 | 62 | @Schema(description = "多端口RTP收流端口范围") |
| 63 | 63 | private String rtpPortRange; |
| 64 | 64 | |
| 65 | + @Schema(description = "RTP发流端口范围") | |
| 66 | + private String sendRtpPortRange; | |
| 67 | + | |
| 65 | 68 | @Schema(description = "assist服务端口") |
| 66 | 69 | private int recordAssistPort; |
| 67 | 70 | |
| ... | ... | @@ -297,4 +300,12 @@ public class MediaServerItem{ |
| 297 | 300 | public void setHookAliveInterval(Float hookAliveInterval) { |
| 298 | 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/service/impl/MediaServerServiceImpl.java
| ... | ... | @@ -11,10 +11,7 @@ import com.genersoft.iot.vmp.conf.UserSetting; |
| 11 | 11 | import com.genersoft.iot.vmp.conf.exception.ControllerException; |
| 12 | 12 | import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
| 13 | 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 | 15 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 19 | 16 | import com.genersoft.iot.vmp.media.zlm.dto.ServerKeepaliveData; |
| 20 | 17 | import com.genersoft.iot.vmp.service.IInviteStreamService; |
| ... | ... | @@ -71,6 +68,9 @@ public class MediaServerServiceImpl implements IMediaServerService { |
| 71 | 68 | private UserSetting userSetting; |
| 72 | 69 | |
| 73 | 70 | @Autowired |
| 71 | + private SendRtpPortManager sendRtpPortManager; | |
| 72 | + | |
| 73 | + @Autowired | |
| 74 | 74 | private AssistRESTfulUtils assistRESTfulUtils; |
| 75 | 75 | |
| 76 | 76 | @Autowired |
| ... | ... | @@ -119,13 +119,40 @@ public class MediaServerServiceImpl implements IMediaServerService { |
| 119 | 119 | if (ssrcFactory.hasMediaServerSSRC(mediaServerItem.getId())) { |
| 120 | 120 | ssrcFactory.initMediaServerSSRC(mediaServerItem.getId(), null); |
| 121 | 121 | } |
| 122 | + if (userSetting.getGbSendStreamStrict()) { | |
| 123 | + int startPort = 50000; | |
| 124 | + int endPort = 60000; | |
| 125 | + String sendRtpPortRange = mediaServerItem.getSendRtpPortRange(); | |
| 126 | + if (sendRtpPortRange == null) { | |
| 127 | + logger.warn("[zlm] ] 未配置发流端口范围,默认使用50000到60000"); | |
| 128 | + }else { | |
| 129 | + String[] sendRtpPortRangeArray = sendRtpPortRange.trim().split(","); | |
| 130 | + if (sendRtpPortRangeArray.length != 2) { | |
| 131 | + logger.warn("[zlm] ] 发流端口范围错误,默认使用50000到60000"); | |
| 132 | + }else { | |
| 133 | + try { | |
| 134 | + startPort = Integer.parseInt(sendRtpPortRangeArray[0]); | |
| 135 | + endPort = Integer.parseInt(sendRtpPortRangeArray[1]); | |
| 136 | + if (endPort <= startPort) { | |
| 137 | + logger.warn("[zlm] ] 发流端口范围错误,结束端口应大于开始端口,使用默认端口"); | |
| 138 | + startPort = 50000; | |
| 139 | + endPort = 60000; | |
| 140 | + } | |
| 141 | + | |
| 142 | + }catch (NumberFormatException e) { | |
| 143 | + logger.warn("[zlm] ] 发流端口范围错误,默认使用50000到60000"); | |
| 144 | + } | |
| 145 | + } | |
| 146 | + } | |
| 147 | + logger.info("[[zlm] ] 配置发流端口范围,{}-{}", startPort, endPort); | |
| 148 | + sendRtpPortManager.initServerPort(mediaServerItem.getId(), startPort, endPort); | |
| 149 | + } | |
| 122 | 150 | // 查询redis是否存在此mediaServer |
| 123 | 151 | String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(); |
| 124 | 152 | Boolean hasKey = redisTemplate.hasKey(key); |
| 125 | 153 | if (hasKey != null && ! hasKey) { |
| 126 | 154 | redisTemplate.opsForValue().set(key, mediaServerItem); |
| 127 | 155 | } |
| 128 | - | |
| 129 | 156 | } |
| 130 | 157 | } |
| 131 | 158 | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java
| ... | ... | @@ -314,9 +314,7 @@ public class RedisGbPlayMsgListener implements MessageListener { |
| 314 | 314 | SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, content.getIp(), |
| 315 | 315 | content.getPort(), content.getSsrc(), content.getPlatformId(), |
| 316 | 316 | content.getApp(), content.getStream(), content.getChannelId(), |
| 317 | - content.getTcp(), content.getRtcp(), ssrcFromCallback -> { | |
| 318 | - return querySendRTPServer(content.getPlatformId(), content.getChannelId(), content.getStream(), null) != null; | |
| 319 | - }); | |
| 317 | + content.getTcp(), content.getRtcp()); | |
| 320 | 318 | |
| 321 | 319 | WVPResult<ResponseSendItemMsg> result = new WVPResult<>(); |
| 322 | 320 | result.setCode(0); | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java
| ... | ... | @@ -28,6 +28,7 @@ public interface MediaServerMapper { |
| 28 | 28 | "secret,"+ |
| 29 | 29 | "rtp_enable,"+ |
| 30 | 30 | "rtp_port_range,"+ |
| 31 | + "send_rtp_port_range,"+ | |
| 31 | 32 | "record_assist_port,"+ |
| 32 | 33 | "default_server,"+ |
| 33 | 34 | "create_time,"+ |
| ... | ... | @@ -51,6 +52,7 @@ public interface MediaServerMapper { |
| 51 | 52 | "#{secret}, " + |
| 52 | 53 | "#{rtpEnable}, " + |
| 53 | 54 | "#{rtpPortRange}, " + |
| 55 | + "#{sendRtpPortRange}, " + | |
| 54 | 56 | "#{recordAssistPort}, " + |
| 55 | 57 | "#{defaultServer}, " + |
| 56 | 58 | "#{createTime}, " + |
| ... | ... | @@ -75,6 +77,7 @@ public interface MediaServerMapper { |
| 75 | 77 | "<if test=\"autoConfig != null\">, auto_config=#{autoConfig}</if>" + |
| 76 | 78 | "<if test=\"rtpEnable != null\">, rtp_enable=#{rtpEnable}</if>" + |
| 77 | 79 | "<if test=\"rtpPortRange != null\">, rtp_port_range=#{rtpPortRange}</if>" + |
| 80 | + "<if test=\"sendRtpPortRange != null\">, send_rtp_port_range=#{sendRtpPortRange}</if>" + | |
| 78 | 81 | "<if test=\"secret != null\">, secret=#{secret}</if>" + |
| 79 | 82 | "<if test=\"recordAssistPort != null\">, record_assist_port=#{recordAssistPort}</if>" + |
| 80 | 83 | "<if test=\"hookAliveInterval != null\">, hook_alive_interval=#{hookAliveInterval}</if>" + |
| ... | ... | @@ -98,6 +101,7 @@ public interface MediaServerMapper { |
| 98 | 101 | "<if test=\"autoConfig != null\">, auto_config=#{autoConfig}</if>" + |
| 99 | 102 | "<if test=\"rtpEnable != null\">, rtp_enable=#{rtpEnable}</if>" + |
| 100 | 103 | "<if test=\"rtpPortRange != null\">, rtp_port_range=#{rtpPortRange}</if>" + |
| 104 | + "<if test=\"sendRtpPortRange != null\">, send_rtp_port_range=#{sendRtpPortRange}</if>" + | |
| 101 | 105 | "<if test=\"secret != null\">, secret=#{secret}</if>" + |
| 102 | 106 | "<if test=\"recordAssistPort != null\">, record_assist_port=#{recordAssistPort}</if>" + |
| 103 | 107 | "<if test=\"hookAliveInterval != null\">, hook_alive_interval=#{hookAliveInterval}</if>" + | ... | ... |
web_src/src/components/dialog/MediaServerEdit.vue
| ... | ... | @@ -81,6 +81,7 @@ |
| 81 | 81 | <el-switch active-text="多端口" inactive-text="单端口" @change="portRangeChange" v-model="mediaServerForm.rtpEnable" :disabled="mediaServerForm.defaultServer"></el-switch> |
| 82 | 82 | </el-form-item> |
| 83 | 83 | |
| 84 | + | |
| 84 | 85 | <el-form-item v-if="!mediaServerForm.rtpEnable" label="收流端口" prop="rtpProxyPort"> |
| 85 | 86 | <el-input v-model.number="mediaServerForm.rtpProxyPort" clearable :disabled="mediaServerForm.defaultServer"></el-input> |
| 86 | 87 | </el-form-item> |
| ... | ... | @@ -89,6 +90,11 @@ |
| 89 | 90 | - |
| 90 | 91 | <el-input v-model="rtpPortRange2" placeholder="终止" @change="portRangeChange" clearable style="width: 100px" prop="rtpPortRange2" :disabled="mediaServerForm.defaultServer"></el-input> |
| 91 | 92 | </el-form-item> |
| 93 | + <el-form-item v-if="mediaServerForm.sendRtpEnable" label="发流端口" > | |
| 94 | + <el-input v-model="sendRtpPortRange1" placeholder="起始" @change="portRangeChange" clearable style="width: 100px" prop="rtpPortRange1" :disabled="mediaServerForm.defaultServer"></el-input> | |
| 95 | + - | |
| 96 | + <el-input v-model="sendRtpPortRange2" placeholder="终止" @change="portRangeChange" clearable style="width: 100px" prop="rtpPortRange2" :disabled="mediaServerForm.defaultServer"></el-input> | |
| 97 | + </el-form-item> | |
| 92 | 98 | <el-form-item label="录像管理服务端口" prop="recordAssistPort"> |
| 93 | 99 | <el-input v-model.number="mediaServerForm.recordAssistPort" :disabled="mediaServerForm.defaultServer"> |
| 94 | 100 | <!-- <el-button v-if="mediaServerForm.recordAssistPort > 0" slot="append" type="primary" @click="checkRecordServer">测试</el-button>--> |
| ... | ... | @@ -172,6 +178,7 @@ export default { |
| 172 | 178 | rtmpSSlPort: "", |
| 173 | 179 | rtpEnable: false, |
| 174 | 180 | rtpPortRange: "", |
| 181 | + sendRtpPortRange: "", | |
| 175 | 182 | rtpProxyPort: "", |
| 176 | 183 | rtspPort: "", |
| 177 | 184 | rtspSSLPort: "", |
| ... | ... | @@ -179,6 +186,9 @@ export default { |
| 179 | 186 | rtpPortRange1:30000, |
| 180 | 187 | rtpPortRange2:30500, |
| 181 | 188 | |
| 189 | + sendRtpPortRange1:50000, | |
| 190 | + sendRtpPortRange2:60000, | |
| 191 | + | |
| 182 | 192 | rules: { |
| 183 | 193 | ip: [{ required: true, validator: isValidIp, message: '请输入有效的IP地址', trigger: 'blur' }], |
| 184 | 194 | httpPort: [{ required: true, validator: isValidPort, message: '请输入有效的端口号', trigger: 'blur' }], |
| ... | ... | @@ -214,10 +224,15 @@ export default { |
| 214 | 224 | this.currentStep = 3; |
| 215 | 225 | if (param.rtpPortRange) { |
| 216 | 226 | let rtpPortRange = this.mediaServerForm.rtpPortRange.split(","); |
| 227 | + let sendRtpPortRange = this.mediaServerForm.sendRtpPortRange.split(","); | |
| 217 | 228 | if (rtpPortRange.length > 0) { |
| 218 | 229 | this.rtpPortRange1 = rtpPortRange[0] |
| 219 | 230 | this.rtpPortRange2 = rtpPortRange[1] |
| 220 | 231 | } |
| 232 | + if (sendRtpPortRange.length > 0) { | |
| 233 | + this.sendRtpPortRange1 = sendRtpPortRange[0] | |
| 234 | + this.sendRtpPortRange2 = sendRtpPortRange[1] | |
| 235 | + } | |
| 221 | 236 | } |
| 222 | 237 | } |
| 223 | 238 | }, |
| ... | ... | @@ -240,6 +255,8 @@ export default { |
| 240 | 255 | that.mediaServerForm.autoConfig = true; |
| 241 | 256 | that.rtpPortRange1 = 30000 |
| 242 | 257 | that.rtpPortRange2 = 30500 |
| 258 | + that.sendRtpPortRange1 = 50000 | |
| 259 | + that.sendRtpPortRange2 = 60000 | |
| 243 | 260 | that.serverCheck = 1; |
| 244 | 261 | }else { |
| 245 | 262 | that.serverCheck = -1; |
| ... | ... | @@ -321,12 +338,15 @@ export default { |
| 321 | 338 | rtmpSSlPort: "", |
| 322 | 339 | rtpEnable: false, |
| 323 | 340 | rtpPortRange: "", |
| 341 | + sendRtpPortRange: "", | |
| 324 | 342 | rtpProxyPort: "", |
| 325 | 343 | rtspPort: "", |
| 326 | 344 | rtspSSLPort: "", |
| 327 | 345 | }; |
| 328 | 346 | this.rtpPortRange1 = 30500; |
| 329 | 347 | this.rtpPortRange2 = 30500; |
| 348 | + this.sendRtpPortRange1 = 50000; | |
| 349 | + this.sendRtpPortRange2 = 60000; | |
| 330 | 350 | this.listChangeCallback = null |
| 331 | 351 | this.currentStep = 1; |
| 332 | 352 | }, |
| ... | ... | @@ -351,7 +371,7 @@ export default { |
| 351 | 371 | portRangeChange: function() { |
| 352 | 372 | if (this.mediaServerForm.rtpEnable) { |
| 353 | 373 | this.mediaServerForm.rtpPortRange = this.rtpPortRange1 + "," + this.rtpPortRange2 |
| 354 | - console.log(this.mediaServerForm.rtpPortRange) | |
| 374 | + this.mediaServerForm.sendRtpPortRange = this.sendRtpPortRange1 + "," + this.sendRtpPortRange2 | |
| 355 | 375 | } |
| 356 | 376 | } |
| 357 | 377 | }, | ... | ... |
web_src/src/components/dialog/StreamProxyEdit.vue
| ... | ... | @@ -82,17 +82,21 @@ |
| 82 | 82 | <el-option label="组播" value="2"></el-option> |
| 83 | 83 | </el-select> |
| 84 | 84 | </el-form-item> |
| 85 | + | |
| 85 | 86 | <el-form-item label="无人观看" prop="rtpType" > |
| 86 | - <el-select | |
| 87 | - @change="noneReaderHandler" | |
| 88 | - v-model="proxyParam.noneReader" | |
| 89 | - style="width: 100%" | |
| 90 | - placeholder="请选择无人观看的处理方式" | |
| 91 | - > | |
| 92 | - <el-option label="不做处理" value="0"></el-option> | |
| 93 | - <el-option label="停用" value="1"></el-option> | |
| 94 | - <el-option label="移除" value="2"></el-option> | |
| 95 | - </el-select> | |
| 87 | + <el-radio v-model="proxyParam.noneReader" label="1">不做处理</el-radio> | |
| 88 | + <el-radio v-model="proxyParam.enableDisableNoneReader" label="2">停用</el-radio> | |
| 89 | + <el-radio v-model="proxyParam.enableRemoveNoneReader" label="3">移除</el-radio> | |
| 90 | +<!-- <el-select--> | |
| 91 | +<!-- @change="noneReaderHandler"--> | |
| 92 | +<!-- v-model="proxyParam.noneReader"--> | |
| 93 | +<!-- style="width: 100%"--> | |
| 94 | +<!-- placeholder="请选择无人观看的处理方式"--> | |
| 95 | +<!-- >--> | |
| 96 | +<!-- <el-option label="不做处理" value="0"></el-option>--> | |
| 97 | +<!-- <el-option label="停用" value="1"></el-option>--> | |
| 98 | +<!-- <el-option label="移除" value="2"></el-option>--> | |
| 99 | +<!-- </el-select>--> | |
| 96 | 100 | </el-form-item> |
| 97 | 101 | <el-form-item label="其他选项"> |
| 98 | 102 | <div style="float: left;"> | ... | ... |