New file |
| | |
| | | alter table media_server |
| | | add sendRtpPortRange varchar(50) not null; |
| | |
| | | @Value("${media.rtp.port-range}") |
| | | private String rtpPortRange; |
| | | |
| | | @Value("${media.rtp.send-port-range}") |
| | | private String rtpSendPortRange; |
| | | |
| | | @Value("${media.record-assist-port:0}") |
| | | private Integer recordAssistPort = 0; |
| | | |
| | |
| | | mediaServerItem.setSecret(secret); |
| | | mediaServerItem.setRtpEnable(rtpEnable); |
| | | mediaServerItem.setRtpPortRange(rtpPortRange); |
| | | mediaServerItem.setSendRtpPortRange(rtpSendPortRange); |
| | | mediaServerItem.setRecordAssistPort(recordAssistPort); |
| | | mediaServerItem.setHookAliveInterval(30.00f); |
| | | |
| | |
| | | return false; |
| | | } |
| | | |
| | | public String getRtpSendPortRange() { |
| | | return rtpSendPortRange; |
| | | } |
| | | |
| | | public void setRtpSendPortRange(String rtpSendPortRange) { |
| | | this.rtpSendPortRange = rtpSendPortRange; |
| | | } |
| | | } |
| | |
| | | startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, jsonObject, param, callIdHeader); |
| | | }); |
| | | }else { |
| | | // 妿æ¯éä¸¥æ ¼æ¨¡å¼ï¼éè¦å
³é端å£å ç¨ |
| | | JSONObject startSendRtpStreamResult = null; |
| | | if (sendRtpItem.getLocalPort() != 0) { |
| | | if (zlmrtpServerFactory.releasePort(mediaInfo, sendRtpItem.getSsrc())) { |
| | | startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); |
| | | } |
| | | }else { |
| | | startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); |
| | | } |
| | | JSONObject startSendRtpStreamResult = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); |
| | | if (startSendRtpStreamResult != null) { |
| | | startSendRtpStreamHand(evt, sendRtpItem, parentPlatform, startSendRtpStreamResult, param, callIdHeader); |
| | | } |
| | |
| | | } |
| | | logger.info("[ä¸çº§Invite] {}, å¹³å°ï¼{}ï¼ ééï¼{}, æ¶æµå°åï¼{}:{}ï¼æ¶æµæ¹å¼ï¼{}, ssrcï¼{}", sessionName, username, channelId, addressStr, port, streamTypeStr, ssrc); |
| | | SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, |
| | | device.getDeviceId(), channelId, mediaTransmissionTCP, platform.isRtcp(), ssrcFromCallback -> { |
| | | return redisCatchStorage.querySendRTPServer(platform.getServerGBId(), channelId, null, callIdHeader.getCallId()) != null; |
| | | }); |
| | | device.getDeviceId(), channelId, mediaTransmissionTCP, platform.isRtcp()); |
| | | |
| | | if (tcpActive != null) { |
| | | sendRtpItem.setTcpActive(tcpActive); |
| | |
| | | if (streamReady) { |
| | | // èªå¹³å°å
容 |
| | | SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, |
| | | gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp(), ssrcFromCallback ->{ |
| | | return redisCatchStorage.querySendRTPServer(platform.getServerGBId(), channelId, null, callIdHeader.getCallId()) != null; |
| | | }); |
| | | gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp()); |
| | | |
| | | if (sendRtpItem == null) { |
| | | logger.warn("æå¡å¨ç«¯å£èµæºä¸è¶³"); |
| | |
| | | if (streamReady) { |
| | | // èªå¹³å°å
容 |
| | | SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, |
| | | gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp(), ssrcFromCallback ->{ |
| | | return redisCatchStorage.querySendRTPServer(platform.getServerGBId(), channelId, null, callIdHeader.getCallId()) != null; |
| | | }); |
| | | gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp()); |
| | | |
| | | if (sendRtpItem == null) { |
| | | logger.warn("æå¡å¨ç«¯å£èµæºä¸è¶³"); |
| | |
| | | dynamicTask.stop(callIdHeader.getCallId()); |
| | | if (serverId.equals(userSetting.getServerId())) { |
| | | SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, finalPort, ssrc, requesterId, |
| | | app, stream, channelId, mediaTransmissionTCP, platform.isRtcp(), ssrcFromCallback -> { |
| | | return redisCatchStorage.querySendRTPServer(platform.getServerGBId(), channelId, null, callIdHeader.getCallId()) != null; |
| | | }); |
| | | app, stream, channelId, mediaTransmissionTCP, platform.isRtcp()); |
| | | |
| | | if (sendRtpItem == null) { |
| | | logger.warn("ä¸çº§ç¹æ¶å建sendRTPItem失败ï¼å¯è½æ¯æå¡å¨ç«¯å£èµæºä¸è¶³"); |
New file |
| | |
| | | package com.genersoft.iot.vmp.media.zlm; |
| | | |
| | | import com.genersoft.iot.vmp.conf.UserSetting; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.MediaSendRtpPortInfo; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.data.redis.core.RedisTemplate; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | @Component |
| | | public class SendRtpPortManager { |
| | | |
| | | private final static Logger logger = LoggerFactory.getLogger(SendRtpPortManager.class); |
| | | |
| | | @Autowired |
| | | private UserSetting userSetting; |
| | | |
| | | @Autowired |
| | | private RedisTemplate<Object, Object> redisTemplate; |
| | | |
| | | private final String KEY = "VM_MEDIA_SEND_RTP_PORT_RANGE_"; |
| | | |
| | | |
| | | public void initServerPort(String mediaServerId, int startPort, int endPort){ |
| | | String key = KEY + userSetting.getServerId() + "_" + mediaServerId; |
| | | MediaSendRtpPortInfo mediaSendRtpPortInfo = new MediaSendRtpPortInfo(startPort, endPort, mediaServerId); |
| | | redisTemplate.opsForValue().set(key, mediaSendRtpPortInfo); |
| | | } |
| | | |
| | | public int getNextPort(String mediaServerId) { |
| | | String key = KEY + userSetting.getServerId() + "_" + mediaServerId; |
| | | MediaSendRtpPortInfo mediaSendRtpPortInfo = (MediaSendRtpPortInfo)redisTemplate.opsForValue().get(key); |
| | | if (mediaSendRtpPortInfo == null) { |
| | | logger.warn("[åé端å£ç®¡ç] è·å{}çåéç«¯å£æ¶æªæ¾å°ç«¯å£ä¿¡æ¯", mediaSendRtpPortInfo); |
| | | return 0; |
| | | } |
| | | int port; |
| | | if (mediaSendRtpPortInfo.getCurrent() %2 != 0) { |
| | | port = mediaSendRtpPortInfo.getCurrent() + 1; |
| | | }else { |
| | | port = mediaSendRtpPortInfo.getCurrent() + 2; |
| | | } |
| | | if (port > mediaSendRtpPortInfo.getEnd()) { |
| | | if (mediaSendRtpPortInfo.getStart() %2 != 0) { |
| | | port = mediaSendRtpPortInfo.getStart() + 1; |
| | | }else { |
| | | port = mediaSendRtpPortInfo.getStart(); |
| | | } |
| | | } |
| | | mediaSendRtpPortInfo.setCurrent(port); |
| | | redisTemplate.opsForValue().set(key, mediaSendRtpPortInfo); |
| | | return port; |
| | | } |
| | | } |
| | |
| | | import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
|
| | | import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
| | | import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
| | | import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
| | | import com.genersoft.iot.vmp.vmanager.bean.*;
|
| | | import org.slf4j.Logger;
|
| | | import org.slf4j.LoggerFactory;
|
| | |
| | |
|
| | |
|
| | | HookResultForOnPublish result = HookResultForOnPublish.SUCCESS();
|
| | | if (!"rtp".equals(param.getApp())) {
|
| | | result.setEnable_audio(true);
|
| | | }
|
| | |
|
| | | taskExecutor.execute(() -> {
|
| | | ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_publish, json);
|
| | |
| | | }
|
| | | }
|
| | |
|
| | | String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "*";
|
| | | // å°ä¿¡æ¯åå
¥redisä¸ï¼ä»¥å¤åç¨
|
| | | List<Object> scan = RedisUtil.scan(redisTemplate, receiveKey);
|
| | | if (scan.size()>0) {
|
| | | for (Object o : scan) {
|
| | | String key = (String) o;
|
| | | OtherRtpSendInfo otherRtpSendInfo = (OtherRtpSendInfo)redisTemplate.opsForValue().get(key);
|
| | | if (otherRtpSendInfo != null && otherRtpSendInfo.getStream().equalsIgnoreCase(param.getStream())) {
|
| | | result.setEnable_audio(true);
|
| | | result.setEnable_mp4(true);
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | if (mediaInfo.getRecordAssistPort() > 0 && userSetting.getRecordPath() == null) {
|
| | | logger.info("æ¨æµæ¶åç°å°æªè®¾ç½®å½åè·¯å¾ï¼ä»assistæå¡ä¸è¯»å");
|
| | | JSONObject info = assistRESTfulUtils.getInfo(mediaInfo, null);
|
| | |
| | | }
|
| | | }
|
| | | }
|
| | | if (param.getApp().equalsIgnoreCase("rtp")) {
|
| | | String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_" + param.getStream();
|
| | | System.out.println(receiveKey);
|
| | | OtherRtpSendInfo otherRtpSendInfo = (OtherRtpSendInfo)redisTemplate.opsForValue().get(receiveKey);
|
| | | System.out.println("otherRtpSendInfo != null ====>" + (otherRtpSendInfo != null));
|
| | | if (otherRtpSendInfo != null) {
|
| | | System.out.println("otherRtpSendInfo != null");
|
| | | result.setEnable_audio(true);
|
| | | result.setEnable_mp4(true);
|
| | | }
|
| | | }
|
| | | logger.info("[ZLM HOOK]æ¨æµé´æ ååºï¼{}->{}->>>>{}", param.getMediaServerId(), param, result);
|
| | | return result;
|
| | | }
|
| | |
|
| | |
| | | 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.common.CommonCallback; |
| | | import com.genersoft.iot.vmp.conf.UserSetting; |
| | | import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForRtpServerTimeout; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import java.util.*; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | @Component |
| | | public class ZLMRTPServerFactory { |
| | |
| | | @Autowired |
| | | private ZlmHttpHookSubscribe hookSubscribe; |
| | | |
| | | private int[] portRangeArray = new int[2]; |
| | | |
| | | public int getFreePort(MediaServerItem mediaServerItem, int startPort, int endPort, List<Integer> usedFreelist) { |
| | | if (endPort <= startPort) { |
| | | return -1; |
| | | } |
| | | if (usedFreelist == null) { |
| | | usedFreelist = new ArrayList<>(); |
| | | } |
| | | JSONObject listRtpServerJsonResult = zlmresTfulUtils.listRtpServer(mediaServerItem); |
| | | if (listRtpServerJsonResult != null) { |
| | | JSONArray data = listRtpServerJsonResult.getJSONArray("data"); |
| | | if (data != null) { |
| | | for (int i = 0; i < data.size(); i++) { |
| | | JSONObject dataItem = data.getJSONObject(i); |
| | | usedFreelist.add(dataItem.getInteger("port")); |
| | | } |
| | | } |
| | | } |
| | | |
| | | Map<String, Object> param = new HashMap<>(); |
| | | int result = -1; |
| | | // è®¾ç½®æ¨æµç«¯å£ |
| | | if (startPort%2 == 1) { |
| | | startPort ++; |
| | | } |
| | | boolean checkPort = false; |
| | | for (int i = startPort; i < endPort + 1; i+=2) { |
| | | if (!usedFreelist.contains(i)){ |
| | | checkPort = true; |
| | | startPort = i; |
| | | break; |
| | | } |
| | | } |
| | | if (!checkPort) { |
| | | logger.warn("æªæ¾å°èç¹{}ä¸èå´[{}-{}]ç空é²ç«¯å£", mediaServerItem.getId(), startPort, endPort); |
| | | return -1; |
| | | } |
| | | param.put("port", startPort); |
| | | String stream = UUID.randomUUID().toString(); |
| | | param.put("enable_tcp", 1); |
| | | param.put("stream_id", stream); |
| | | // param.put("port", 0); |
| | | JSONObject openRtpServerResultJson = zlmresTfulUtils.openRtpServer(mediaServerItem, param); |
| | | |
| | | if (openRtpServerResultJson != null) { |
| | | if (openRtpServerResultJson.getInteger("code") == 0) { |
| | | result= openRtpServerResultJson.getInteger("port"); |
| | | Map<String, Object> closeRtpServerParam = new HashMap<>(); |
| | | closeRtpServerParam.put("stream_id", stream); |
| | | zlmresTfulUtils.closeRtpServer(mediaServerItem, closeRtpServerParam); |
| | | }else { |
| | | usedFreelist.add(startPort); |
| | | startPort +=2; |
| | | result = getFreePort(mediaServerItem, startPort, endPort,usedFreelist); |
| | | } |
| | | }else { |
| | | // æ£æ¥ZLMç¶æ |
| | | logger.error("å建RTP Server 失败 {}: è¯·æ£æ¥ZLMæå¡", param.get("port")); |
| | | } |
| | | return result; |
| | | } |
| | | @Autowired |
| | | private SendRtpPortManager sendRtpPortManager; |
| | | |
| | | /** |
| | | * å¼å¯rtpServer |
| | |
| | | * @return SendRtpItem |
| | | */ |
| | | public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, |
| | | String deviceId, String channelId, boolean tcp, boolean rtcp, KeepPortCallback callback){ |
| | | String deviceId, String channelId, boolean tcp, boolean rtcp){ |
| | | |
| | | // é»è®¤ä¸ºéæºç«¯å£ |
| | | int localPort = 0; |
| | | if (userSetting.getGbSendStreamStrict()) { |
| | | if (userSetting.getGbSendStreamStrict()) { |
| | | localPort = keepPort(serverItem, ssrc, localPort, callback); |
| | | localPort = sendRtpPortManager.getNextPort(serverItem.getId()); |
| | | if (localPort == 0) { |
| | | return null; |
| | | } |
| | |
| | | * @return SendRtpItem |
| | | */ |
| | | public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, |
| | | String app, String stream, String channelId, boolean tcp, boolean rtcp, KeepPortCallback callback){ |
| | | String app, String stream, String channelId, boolean tcp, boolean rtcp){ |
| | | // é»è®¤ä¸ºéæºç«¯å£ |
| | | int localPort = 0; |
| | | if (userSetting.getGbSendStreamStrict()) { |
| | | localPort = keepPort(serverItem, ssrc, localPort, callback); |
| | | localPort = sendRtpPortManager.getNextPort(serverItem.getId()); |
| | | if (localPort == 0) { |
| | | return null; |
| | | } |
| | |
| | | sendRtpItem.setMediaServerId(serverItem.getId()); |
| | | sendRtpItem.setRtcp(rtcp); |
| | | return sendRtpItem; |
| | | } |
| | | |
| | | public interface KeepPortCallback{ |
| | | Boolean keep(String ssrc); |
| | | } |
| | | |
| | | /** |
| | | * ä¿æç«¯å£ï¼ç´å°éè¦éè¦åæµæ¶åéæ¾ |
| | | */ |
| | | public int keepPort(MediaServerItem serverItem, String ssrc, int localPort, KeepPortCallback keepPortCallback) { |
| | | Map<String, Object> param = new HashMap<>(3); |
| | | param.put("port", localPort); |
| | | 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ä¹ä¼ä»è¿éè¿å
¥ç³»ç» |
| | | Integer finalLocalPort = localPort; |
| | | hookSubscribe.addSubscribe(hookSubscribeForRtpServerTimeout, |
| | | (MediaServerItem mediaServerItem, JSONObject response)->{ |
| | | System.out.println("çå¬ç«¯å£å°æç»§ç»ä¿æçå¬"); |
| | | System.out.println(response); |
| | | if (ssrc.equals(response.getString("stream_id"))) { |
| | | if (keepPortCallback.keep(ssrc)) { |
| | | logger.info("[ä¸çº§ç¹æ] {}->çå¬ç«¯å£å°æç»§ç»ä¿æçå¬", ssrc); |
| | | keepPort(serverItem, ssrc, finalLocalPort, keepPortCallback); |
| | | }else { |
| | | logger.info("[ä¸çº§ç¹æ] {}->åéåæ¶ï¼æ éç»§ç»çå¬", ssrc); |
| | | releasePort(serverItem, ssrc); |
| | | } |
| | | } |
| | | |
| | | }); |
| | | logger.info("[ä¸çº§ç¹æ] {}->çå¬ç«¯å£: {}", ssrc, localPort); |
| | | }else { |
| | | logger.info("[ä¸çº§ç¹æ] çå¬ç«¯å£å¤±è´¥: {}", ssrc); |
| | | } |
| | | return localPort; |
| | | } |
| | | |
| | | /** |
| | | * éæ¾ä¿æçç«¯å£ |
| | | */ |
| | | public boolean releasePort(MediaServerItem serverItem, String ssrc) { |
| | | logger.info("[ä¸çº§ç¹æ] {}->éæ¾çå¬ç«¯å£", ssrc); |
| | | boolean closeRTPServerResult = closeRtpServer(serverItem, ssrc); |
| | | HookSubscribeForRtpServerTimeout hookSubscribeForRtpServerTimeout = HookSubscribeFactory.on_rtp_server_timeout(ssrc, null, serverItem.getId()); |
| | | // 订é
zlmå¯å¨äºä»¶, æ°çzlmä¹ä¼ä»è¿éè¿å
¥ç³»ç» |
| | | hookSubscribe.removeSubscribe(hookSubscribeForRtpServerTimeout); |
| | | return closeRTPServerResult; |
| | | } |
| | | |
| | | /** |
New file |
| | |
| | | package com.genersoft.iot.vmp.media.zlm.dto; |
| | | |
| | | public class MediaSendRtpPortInfo { |
| | | |
| | | private int start; |
| | | private int end; |
| | | private String mediaServerId; |
| | | |
| | | private int current; |
| | | |
| | | |
| | | public MediaSendRtpPortInfo(int start, int end, String mediaServerId) { |
| | | this.start = start; |
| | | this.current = start; |
| | | this.end = end; |
| | | this.mediaServerId = mediaServerId; |
| | | } |
| | | |
| | | public int getStart() { |
| | | return start; |
| | | } |
| | | |
| | | public void setStart(int start) { |
| | | this.start = start; |
| | | } |
| | | |
| | | public int getEnd() { |
| | | return end; |
| | | } |
| | | |
| | | public void setEnd(int end) { |
| | | this.end = end; |
| | | } |
| | | |
| | | public String getMediaServerId() { |
| | | return mediaServerId; |
| | | } |
| | | |
| | | public void setMediaServerId(String mediaServerId) { |
| | | this.mediaServerId = mediaServerId; |
| | | } |
| | | |
| | | public int getCurrent() { |
| | | return current; |
| | | } |
| | | |
| | | public void setCurrent(int current) { |
| | | this.current = current; |
| | | } |
| | | } |
| | |
| | | @Schema(description = "å¤ç«¯å£RTPæ¶æµç«¯å£èå´") |
| | | private String rtpPortRange; |
| | | |
| | | @Schema(description = "RTPåæµç«¯å£èå´") |
| | | private String sendRtpPortRange; |
| | | |
| | | @Schema(description = "assistæå¡ç«¯å£") |
| | | private int recordAssistPort; |
| | | |
| | |
| | | public void setHookAliveInterval(Float hookAliveInterval) { |
| | | this.hookAliveInterval = hookAliveInterval; |
| | | } |
| | | |
| | | public String getSendRtpPortRange() { |
| | | return sendRtpPortRange; |
| | | } |
| | | |
| | | public void setSendRtpPortRange(String sendRtpPortRange) { |
| | | this.sendRtpPortRange = sendRtpPortRange; |
| | | } |
| | | } |
| | |
| | | public void setMp4_save_path(String mp4_save_path) { |
| | | this.mp4_save_path = mp4_save_path; |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return "HookResultForOnPublish{" + |
| | | "enable_audio=" + enable_audio + |
| | | ", enable_mp4=" + enable_mp4 + |
| | | ", mp4_max_second=" + mp4_max_second + |
| | | ", mp4_save_path='" + mp4_save_path + '\'' + |
| | | '}'; |
| | | } |
| | | } |
| | |
| | | import com.genersoft.iot.vmp.conf.exception.ControllerException; |
| | | import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
| | | import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; |
| | | import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils; |
| | | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; |
| | | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
| | | import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; |
| | | import com.genersoft.iot.vmp.media.zlm.*; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.ServerKeepaliveData; |
| | | import com.genersoft.iot.vmp.service.IMediaServerService; |
| | |
| | | private UserSetting userSetting; |
| | | |
| | | @Autowired |
| | | private SendRtpPortManager sendRtpPortManager; |
| | | |
| | | |
| | | @Autowired |
| | | private AssistRESTfulUtils assistRESTfulUtils; |
| | | |
| | | @Autowired |
| | |
| | | if (ssrcFactory.hasMediaServerSSRC(mediaServerItem.getId())) { |
| | | ssrcFactory.initMediaServerSSRC(mediaServerItem.getId(), null); |
| | | } |
| | | if (userSetting.getGbSendStreamStrict()) { |
| | | int startPort = 50000; |
| | | int endPort = 60000; |
| | | String sendRtpPortRange = mediaServerItem.getSendRtpPortRange(); |
| | | if (sendRtpPortRange == null) { |
| | | logger.warn("[zlm] ] æªé
ç½®åæµç«¯å£èå´ï¼é»è®¤ä½¿ç¨50000å°60000"); |
| | | }else { |
| | | String[] sendRtpPortRangeArray = sendRtpPortRange.trim().split(","); |
| | | if (sendRtpPortRangeArray.length != 2) { |
| | | logger.warn("[zlm] ] åæµç«¯å£èå´é误ï¼é»è®¤ä½¿ç¨50000å°60000"); |
| | | }else { |
| | | try { |
| | | startPort = Integer.parseInt(sendRtpPortRangeArray[0]); |
| | | endPort = Integer.parseInt(sendRtpPortRangeArray[1]); |
| | | if (endPort <= startPort) { |
| | | logger.warn("[zlm] ] åæµç«¯å£èå´é误ï¼ç»æç«¯å£åºå¤§äºå¼å§ç«¯å£,使ç¨é»è®¤ç«¯å£"); |
| | | startPort = 50000; |
| | | endPort = 60000; |
| | | } |
| | | |
| | | }catch (NumberFormatException e) { |
| | | logger.warn("[zlm] ] åæµç«¯å£èå´é误ï¼é»è®¤ä½¿ç¨50000å°60000"); |
| | | } |
| | | } |
| | | } |
| | | logger.info("[[zlm] ] é
ç½®åæµç«¯å£èå´ï¼{}-{}", startPort, endPort); |
| | | sendRtpPortManager.initServerPort(mediaServerItem.getId(), startPort, endPort); |
| | | } |
| | | // æ¥è¯¢redisæ¯å¦å卿¤mediaServer |
| | | String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(); |
| | | Boolean hasKey = redisTemplate.hasKey(key); |
| | | if (hasKey != null && ! hasKey) { |
| | | redisTemplate.opsForValue().set(key, mediaServerItem); |
| | | } |
| | | |
| | | } |
| | | } |
| | | |
| | |
| | | SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, content.getIp(), |
| | | content.getPort(), content.getSsrc(), content.getPlatformId(), |
| | | content.getApp(), content.getStream(), content.getChannelId(), |
| | | content.getTcp(), content.getRtcp(), ssrcFromCallback -> { |
| | | return querySendRTPServer(content.getPlatformId(), content.getChannelId(), content.getStream(), null) != null; |
| | | }); |
| | | content.getTcp(), content.getRtcp()); |
| | | |
| | | WVPResult<ResponseSendItemMsg> result = new WVPResult<>(); |
| | | result.setCode(0); |
| | |
| | | "secret, " + |
| | | "rtpEnable, " + |
| | | "rtpPortRange, " + |
| | | "sendRtpPortRange, " + |
| | | "recordAssistPort, " + |
| | | "defaultServer, " + |
| | | "createTime, " + |
| | |
| | | "#{secret}, " + |
| | | "#{rtpEnable}, " + |
| | | "#{rtpPortRange}, " + |
| | | "#{sendRtpPortRange}, " + |
| | | "#{recordAssistPort}, " + |
| | | "#{defaultServer}, " + |
| | | "#{createTime}, " + |
| | |
| | | "<if test=\"autoConfig != null\">, autoConfig=#{autoConfig}</if>" + |
| | | "<if test=\"rtpEnable != null\">, rtpEnable=#{rtpEnable}</if>" + |
| | | "<if test=\"rtpPortRange != null\">, rtpPortRange=#{rtpPortRange}</if>" + |
| | | "<if test=\"sendRtpPortRange != null\">, sendRtpPortRange=#{sendRtpPortRange}</if>" + |
| | | "<if test=\"secret != null\">, secret=#{secret}</if>" + |
| | | "<if test=\"recordAssistPort != null\">, recordAssistPort=#{recordAssistPort}</if>" + |
| | | "<if test=\"hookAliveInterval != null\">, hookAliveInterval=#{hookAliveInterval}</if>" + |
| | |
| | | "<if test=\"autoConfig != null\">, autoConfig=#{autoConfig}</if>" + |
| | | "<if test=\"rtpEnable != null\">, rtpEnable=#{rtpEnable}</if>" + |
| | | "<if test=\"rtpPortRange != null\">, rtpPortRange=#{rtpPortRange}</if>" + |
| | | "<if test=\"sendRtpPortRange != null\">, sendRtpPortRange=#{sendRtpPortRange}</if>" + |
| | | "<if test=\"secret != null\">, secret=#{secret}</if>" + |
| | | "<if test=\"recordAssistPort != null\">, recordAssistPort=#{recordAssistPort}</if>" + |
| | | "<if test=\"hookAliveInterval != null\">, hookAliveInterval=#{hookAliveInterval}</if>" + |
| | |
| | | @Override |
| | | public String toString() { |
| | | return "OtherRtpSendInfo{" + |
| | | "ip='" + ip + '\'' + |
| | | " ip='" + ip + '\'' + |
| | | ", port=" + port + |
| | | ", receiveIp='" + receiveIp + '\'' + |
| | | ", receivePort=" + receivePort + |
| | |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.genersoft.iot.vmp.common.VideoManagerConstants; |
| | | import com.genersoft.iot.vmp.conf.DynamicTask; |
| | | import com.genersoft.iot.vmp.conf.SipConfig; |
| | | import com.genersoft.iot.vmp.conf.UserSetting; |
| | | import com.genersoft.iot.vmp.conf.VersionInfo; |
| | | import com.genersoft.iot.vmp.conf.exception.ControllerException; |
| | | import com.genersoft.iot.vmp.media.zlm.SendRtpPortManager; |
| | | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
| | | import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForRtpServerTimeout; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| | | import com.genersoft.iot.vmp.service.IDeviceChannelService; |
| | | import com.genersoft.iot.vmp.service.IDeviceService; |
| | | import com.genersoft.iot.vmp.service.IMediaServerService; |
| | | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| | | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; |
| | | import com.genersoft.iot.vmp.vmanager.bean.OtherRtpSendInfo; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.data.redis.core.RedisTemplate; |
| | | import org.springframework.util.ObjectUtils; |
| | | import org.springframework.web.bind.annotation.*; |
| | |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | import java.util.UUID; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | @SuppressWarnings("rawtypes") |
| | | @Tag(name = "ç¬¬ä¸æ¹æå¡å¯¹æ¥") |
| | |
| | | private IMediaServerService mediaServerService; |
| | | |
| | | @Autowired |
| | | private VersionInfo versionInfo; |
| | | |
| | | @Autowired |
| | | private SipConfig sipConfig; |
| | | private SendRtpPortManager sendRtpPortManager; |
| | | |
| | | @Autowired |
| | | private UserSetting userSetting; |
| | | |
| | | @Autowired |
| | | private IDeviceService deviceService; |
| | | |
| | | @Autowired |
| | | private IDeviceChannelService channelService; |
| | | |
| | | @Autowired |
| | | private DynamicTask dynamicTask; |
| | |
| | | |
| | | @Autowired |
| | | private RedisTemplate<Object, Object> redisTemplate; |
| | | |
| | | |
| | | @Value("${server.port}") |
| | | private int serverPort; |
| | | |
| | | |
| | | @Autowired |
| | | private IRedisCatchStorage redisCatchStorage; |
| | | |
| | | |
| | | @GetMapping(value = "/receive/open") |
| | |
| | | otherRtpSendInfo.setReceivePort(localPort); |
| | | otherRtpSendInfo.setCallId(callId); |
| | | otherRtpSendInfo.setStream(stream); |
| | | String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + stream; |
| | | String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_" + stream; |
| | | // å°ä¿¡æ¯åå
¥redisä¸ï¼ä»¥å¤åç¨ |
| | | redisTemplate.opsForValue().set(receiveKey, otherRtpSendInfo); |
| | | if (isSend != null && isSend) { |
| | | String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + callId; |
| | | String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + "_" + callId; |
| | | // é¢åå»ºåæµä¿¡æ¯ |
| | | int port = zlmServerFactory.keepPort(mediaServerItem, callId, 0, ssrc1 -> { |
| | | return redisTemplate.opsForValue().get(key) != null; |
| | | }); |
| | | |
| | | int port = sendRtpPortManager.getNextPort(mediaServerItem.getId()); |
| | | // å°ä¿¡æ¯åå
¥redisä¸ï¼ä»¥å¤åç¨ |
| | | redisTemplate.opsForValue().set(key, otherRtpSendInfo); |
| | | // 设置è¶
æ¶ä»»å¡ï¼è¶
æ¶æªä½¿ç¨ï¼åèªå¨ç§»é¤ï¼å¹¶å
³é端å£ä¿æ, é»è®¤äºåé |
| | | dynamicTask.startDelay(key, ()->{ |
| | | logger.info("[ç¬¬ä¸æ¹æå¡å¯¹æ¥->å¼å¯æ¶æµåè·ååæµä¿¡æ¯] 端å£ä¿æè¶
æ¶ callId->{}", callId); |
| | | redisTemplate.delete(key); |
| | | zlmServerFactory.releasePort(mediaServerItem, callId); |
| | | }, 15000); |
| | | redisTemplate.opsForValue().set(key, otherRtpSendInfo, 300, TimeUnit.SECONDS); |
| | | otherRtpSendInfo.setIp(mediaServerItem.getSdpIp()); |
| | | otherRtpSendInfo.setPort(port); |
| | | logger.info("[ç¬¬ä¸æ¹æå¡å¯¹æ¥->å¼å¯æ¶æµåè·ååæµä¿¡æ¯] ç»æï¼callId->{}ï¼ {}", callId, otherRtpSendInfo); |
| | |
| | | logger.info("[ç¬¬ä¸æ¹æå¡å¯¹æ¥->å
³éæ¶æµ] stream->{}", stream); |
| | | MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer(); |
| | | zlmServerFactory.closeRtpServer(mediaServerItem,stream); |
| | | String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + stream; |
| | | String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_" + stream; |
| | | // å°ä¿¡æ¯åå
¥redisä¸ï¼ä»¥å¤åç¨ |
| | | redisTemplate.delete(receiveKey); |
| | | } |
| | |
| | | streamType = 1; |
| | | } |
| | | MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer(); |
| | | String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + callId; |
| | | String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + "_" + callId; |
| | | OtherRtpSendInfo sendInfo = (OtherRtpSendInfo)redisTemplate.opsForValue().get(key); |
| | | if (sendInfo != null) { |
| | | zlmServerFactory.releasePort(mediaServerItem, callId); |
| | | }else { |
| | | if (sendInfo == null) { |
| | | sendInfo = new OtherRtpSendInfo(); |
| | | } |
| | | sendInfo.setPushApp(app); |
| | |
| | | param.put("only_audio", onlyAudio ? "1" : "0"); |
| | | param.put("pt", pt); |
| | | |
| | | dynamicTask.stop(key); |
| | | Boolean streamReady = zlmServerFactory.isStreamReady(mediaServerItem, app, stream); |
| | | if (streamReady) { |
| | | logger.info("[ç¬¬ä¸æ¹æå¡å¯¹æ¥->åéæµ] æµåå¨ï¼å¼å§åæµï¼callId->{}", callId); |
| | |
| | | @Parameter(name = "callId", description = "æ´ä¸ªè¿ç¨çå¯ä¸æ è¯ï¼ä¸ä¼ å使ç¨éæºç«¯å£åæµ", required = true) |
| | | public void closeSendRTP(String callId) { |
| | | logger.info("[ç¬¬ä¸æ¹æå¡å¯¹æ¥->å
³éåéæµ] callId->{}", callId); |
| | | String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + callId; |
| | | String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + "_" + callId; |
| | | OtherRtpSendInfo sendInfo = (OtherRtpSendInfo)redisTemplate.opsForValue().get(key); |
| | | if (sendInfo == null){ |
| | | throw new ControllerException(ErrorCode.ERROR100.getCode(), "æªå¼å¯åæµ"); |
| | |
| | | - |
| | | <el-input v-model="rtpPortRange2" placeholder="ç»æ¢" @change="portRangeChange" clearable style="width: 100px" prop="rtpPortRange2" :disabled="mediaServerForm.defaultServer"></el-input> |
| | | </el-form-item> |
| | | <el-form-item v-if="mediaServerForm.sendRtpEnable" label="åæµç«¯å£" > |
| | | <el-input v-model="sendRtpPortRange1" placeholder="èµ·å§" @change="portRangeChange" clearable style="width: 100px" prop="rtpPortRange1" :disabled="mediaServerForm.defaultServer"></el-input> |
| | | - |
| | | <el-input v-model="sendRtpPortRange2" placeholder="ç»æ¢" @change="portRangeChange" clearable style="width: 100px" prop="rtpPortRange2" :disabled="mediaServerForm.defaultServer"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="å½å管çæå¡ç«¯å£" prop="recordAssistPort"> |
| | | <el-input v-model.number="mediaServerForm.recordAssistPort" :disabled="mediaServerForm.defaultServer"> |
| | | <!-- <el-button v-if="mediaServerForm.recordAssistPort > 0" slot="append" type="primary" @click="checkRecordServer">æµè¯</el-button>--> |
| | |
| | | rtmpSSlPort: "", |
| | | rtpEnable: false, |
| | | rtpPortRange: "", |
| | | sendRtpPortRange: "", |
| | | rtpProxyPort: "", |
| | | rtspPort: "", |
| | | rtspSSLPort: "", |
| | | }, |
| | | rtpPortRange1:30000, |
| | | rtpPortRange2:30500, |
| | | |
| | | sendRtpPortRange1:50000, |
| | | sendRtpPortRange2:60000, |
| | | |
| | | rules: { |
| | | ip: [{ required: true, validator: isValidIp, message: '请è¾å
¥ææçIPå°å', trigger: 'blur' }], |
| | |
| | | this.currentStep = 3; |
| | | if (param.rtpPortRange) { |
| | | let rtpPortRange = this.mediaServerForm.rtpPortRange.split(","); |
| | | let sendRtpPortRange = this.mediaServerForm.sendRtpPortRange.split(","); |
| | | if (rtpPortRange.length > 0) { |
| | | this.rtpPortRange1 = rtpPortRange[0] |
| | | this.rtpPortRange2 = rtpPortRange[1] |
| | | } |
| | | if (sendRtpPortRange.length > 0) { |
| | | this.sendRtpPortRange1 = sendRtpPortRange[0] |
| | | this.sendRtpPortRange2 = sendRtpPortRange[1] |
| | | } |
| | | } |
| | | } |
| | |
| | | that.mediaServerForm.autoConfig = true; |
| | | that.rtpPortRange1 = 30000 |
| | | that.rtpPortRange2 = 30500 |
| | | that.sendRtpPortRange1 = 50000 |
| | | that.sendRtpPortRange2 = 60000 |
| | | that.serverCheck = 1; |
| | | }else { |
| | | that.serverCheck = -1; |
| | |
| | | rtmpSSlPort: "", |
| | | rtpEnable: false, |
| | | rtpPortRange: "", |
| | | sendRtpPortRange: "", |
| | | rtpProxyPort: "", |
| | | rtspPort: "", |
| | | rtspSSLPort: "", |
| | | }; |
| | | this.rtpPortRange1 = 30500; |
| | | this.rtpPortRange2 = 30500; |
| | | this.sendRtpPortRange1 = 50000; |
| | | this.sendRtpPortRange2 = 60000; |
| | | this.listChangeCallback = null |
| | | this.currentStep = 1; |
| | | }, |
| | |
| | | portRangeChange: function() { |
| | | if (this.mediaServerForm.rtpEnable) { |
| | | this.mediaServerForm.rtpPortRange = this.rtpPortRange1 + "," + this.rtpPortRange2 |
| | | console.log(this.mediaServerForm.rtpPortRange) |
| | | this.mediaServerForm.sendRtpPortRange = this.sendRtpPortRange1 + "," + this.sendRtpPortRange2 |
| | | } |
| | | } |
| | | }, |