Commit 0858f7995b8236d79c6e39a5974cb7a13bcb4e3e
1 parent
3dfbc843
优化ssrc存储结构,避免因为大量ssrc存在MediaServer中导致redis读取超时
Showing
10 changed files
with
213 additions
and
258 deletions
src/main/java/com/genersoft/iot/vmp/conf/redis/RedisConfig.java
| @@ -9,12 +9,8 @@ import org.springframework.context.annotation.Bean; | @@ -9,12 +9,8 @@ import org.springframework.context.annotation.Bean; | ||
| 9 | import org.springframework.context.annotation.Configuration; | 9 | import org.springframework.context.annotation.Configuration; |
| 10 | import org.springframework.core.annotation.Order; | 10 | import org.springframework.core.annotation.Order; |
| 11 | import org.springframework.data.redis.connection.RedisConnectionFactory; | 11 | import org.springframework.data.redis.connection.RedisConnectionFactory; |
| 12 | -import org.springframework.data.redis.core.RedisTemplate; | ||
| 13 | import org.springframework.data.redis.listener.PatternTopic; | 12 | import org.springframework.data.redis.listener.PatternTopic; |
| 14 | import org.springframework.data.redis.listener.RedisMessageListenerContainer; | 13 | import org.springframework.data.redis.listener.RedisMessageListenerContainer; |
| 15 | -import org.springframework.data.redis.serializer.StringRedisSerializer; | ||
| 16 | - | ||
| 17 | -import com.genersoft.iot.vmp.utils.redis.FastJsonRedisSerializer; | ||
| 18 | 14 | ||
| 19 | 15 | ||
| 20 | /** | 16 | /** |
| @@ -48,21 +44,7 @@ public class RedisConfig extends CachingConfigurerSupport { | @@ -48,21 +44,7 @@ public class RedisConfig extends CachingConfigurerSupport { | ||
| 48 | @Autowired | 44 | @Autowired |
| 49 | private RedisPushStreamResponseListener redisPushStreamResponseListener; | 45 | private RedisPushStreamResponseListener redisPushStreamResponseListener; |
| 50 | 46 | ||
| 51 | - @Bean | ||
| 52 | - public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { | ||
| 53 | - RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>(); | ||
| 54 | - // 使用fastJson序列化 | ||
| 55 | - FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class); | ||
| 56 | - // value值的序列化采用fastJsonRedisSerializer | ||
| 57 | - redisTemplate.setValueSerializer(fastJsonRedisSerializer); | ||
| 58 | - redisTemplate.setHashValueSerializer(fastJsonRedisSerializer); | ||
| 59 | - | ||
| 60 | - // key的序列化采用StringRedisSerializer | ||
| 61 | - redisTemplate.setKeySerializer(new StringRedisSerializer()); | ||
| 62 | - redisTemplate.setHashKeySerializer(new StringRedisSerializer()); | ||
| 63 | - redisTemplate.setConnectionFactory(redisConnectionFactory); | ||
| 64 | - return redisTemplate; | ||
| 65 | - } | 47 | + |
| 66 | 48 | ||
| 67 | 49 | ||
| 68 | /** | 50 | /** |
src/main/java/com/genersoft/iot/vmp/conf/redis/RedisTemplateConfig.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.conf.redis; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.utils.redis.FastJsonRedisSerializer; | ||
| 4 | +import org.springframework.context.annotation.Bean; | ||
| 5 | +import org.springframework.context.annotation.Configuration; | ||
| 6 | +import org.springframework.data.redis.connection.RedisConnectionFactory; | ||
| 7 | +import org.springframework.data.redis.core.RedisTemplate; | ||
| 8 | +import org.springframework.data.redis.serializer.StringRedisSerializer; | ||
| 9 | + | ||
| 10 | +@Configuration | ||
| 11 | +public class RedisTemplateConfig { | ||
| 12 | + | ||
| 13 | + @Bean | ||
| 14 | + public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { | ||
| 15 | + RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>(); | ||
| 16 | + // 使用fastJson序列化 | ||
| 17 | + FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class); | ||
| 18 | + // value值的序列化采用fastJsonRedisSerializer | ||
| 19 | + redisTemplate.setValueSerializer(fastJsonRedisSerializer); | ||
| 20 | + redisTemplate.setHashValueSerializer(fastJsonRedisSerializer); | ||
| 21 | + | ||
| 22 | + // key的序列化采用StringRedisSerializer | ||
| 23 | + redisTemplate.setKeySerializer(new StringRedisSerializer()); | ||
| 24 | + redisTemplate.setHashKeySerializer(new StringRedisSerializer()); | ||
| 25 | + redisTemplate.setConnectionFactory(redisConnectionFactory); | ||
| 26 | + return redisTemplate; | ||
| 27 | + } | ||
| 28 | +} |
src/main/java/com/genersoft/iot/vmp/gb28181/session/SSRCFactory.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.gb28181.session; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.conf.SipConfig; | ||
| 4 | +import org.springframework.beans.factory.annotation.Autowired; | ||
| 5 | +import org.springframework.data.redis.core.StringRedisTemplate; | ||
| 6 | +import org.springframework.stereotype.Component; | ||
| 7 | + | ||
| 8 | +import java.util.ArrayList; | ||
| 9 | +import java.util.List; | ||
| 10 | +import java.util.Set; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * ssrc使用 | ||
| 14 | + */ | ||
| 15 | +@Component | ||
| 16 | +public class SSRCFactory { | ||
| 17 | + | ||
| 18 | + /** | ||
| 19 | + * 播流最大并发个数 | ||
| 20 | + */ | ||
| 21 | + private static final Integer MAX_STREAM_COUNT = 10000; | ||
| 22 | + | ||
| 23 | + /** | ||
| 24 | + * 播流最大并发个数 | ||
| 25 | + */ | ||
| 26 | + private static final String SSRC_INFO_KEY = "VMP_SSRC_INFO_"; | ||
| 27 | + | ||
| 28 | + @Autowired | ||
| 29 | + private StringRedisTemplate redisTemplate; | ||
| 30 | + | ||
| 31 | + @Autowired | ||
| 32 | + private SipConfig sipConfig; | ||
| 33 | + | ||
| 34 | + | ||
| 35 | + public void initMediaServerSSRC(String mediaServerId, Set<String> usedSet) { | ||
| 36 | + String ssrcPrefix = sipConfig.getDomain().substring(3, 8); | ||
| 37 | + String redisKey = SSRC_INFO_KEY + mediaServerId; | ||
| 38 | + List<String> ssrcList = new ArrayList<>(); | ||
| 39 | + for (int i = 1; i < MAX_STREAM_COUNT; i++) { | ||
| 40 | + String ssrc = String.format("%s%04d", ssrcPrefix, i); | ||
| 41 | + | ||
| 42 | + if (null == usedSet || !usedSet.contains(ssrc)) { | ||
| 43 | + ssrcList.add(ssrc); | ||
| 44 | + | ||
| 45 | + } | ||
| 46 | + } | ||
| 47 | + if (redisTemplate.opsForSet().size(redisKey) != null) { | ||
| 48 | + redisTemplate.delete(redisKey); | ||
| 49 | + } | ||
| 50 | + redisTemplate.opsForSet().add(redisKey, ssrcList.toArray(new String[0])); | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + | ||
| 54 | + /** | ||
| 55 | + * 获取视频预览的SSRC值,第一位固定为0 | ||
| 56 | + * | ||
| 57 | + * @return ssrc | ||
| 58 | + */ | ||
| 59 | + public String getPlaySsrc(String mediaServerId) { | ||
| 60 | + return "0" + getSN(mediaServerId); | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + /** | ||
| 64 | + * 获取录像回放的SSRC值,第一位固定为1 | ||
| 65 | + */ | ||
| 66 | + public String getPlayBackSsrc(String mediaServerId) { | ||
| 67 | + return "1" + getSN(mediaServerId); | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + /** | ||
| 71 | + * 释放ssrc,主要用完的ssrc一定要释放,否则会耗尽 | ||
| 72 | + * | ||
| 73 | + * @param ssrc 需要重置的ssrc | ||
| 74 | + */ | ||
| 75 | + public void releaseSsrc(String mediaServerId, String ssrc) { | ||
| 76 | + if (ssrc == null) { | ||
| 77 | + return; | ||
| 78 | + } | ||
| 79 | + String sn = ssrc.substring(1); | ||
| 80 | + String redisKey = SSRC_INFO_KEY + mediaServerId; | ||
| 81 | + redisTemplate.opsForSet().add(redisKey, sn); | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + /** | ||
| 85 | + * 获取后四位数SN,随机数 | ||
| 86 | + */ | ||
| 87 | + private String getSN(String mediaServerId) { | ||
| 88 | + String sn = null; | ||
| 89 | + String redisKey = SSRC_INFO_KEY + mediaServerId; | ||
| 90 | + Long size = redisTemplate.opsForSet().size(redisKey); | ||
| 91 | + if (size == null || size == 0) { | ||
| 92 | + throw new RuntimeException("ssrc已经用完"); | ||
| 93 | + } else { | ||
| 94 | + // 在集合中移除并返回一个随机成员。 | ||
| 95 | + sn = (String) redisTemplate.opsForSet().pop(redisKey); | ||
| 96 | + redisTemplate.opsForSet().remove(redisKey, sn); | ||
| 97 | + } | ||
| 98 | + return sn; | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + /** | ||
| 102 | + * 重置一个流媒体服务的所有ssrc | ||
| 103 | + * | ||
| 104 | + * @param mediaServerId 流媒体服务ID | ||
| 105 | + */ | ||
| 106 | + public void reset(String mediaServerId) { | ||
| 107 | + this.initMediaServerSSRC(mediaServerId, null); | ||
| 108 | + } | ||
| 109 | + | ||
| 110 | + /** | ||
| 111 | + * 是否已经存在了某个MediaServer的SSRC信息 | ||
| 112 | + * | ||
| 113 | + * @param mediaServerId 流媒体服务ID | ||
| 114 | + */ | ||
| 115 | + public boolean hasMediaServerSSRC(String mediaServerId) { | ||
| 116 | + String redisKey = SSRC_INFO_KEY + mediaServerId; | ||
| 117 | + return redisTemplate.opsForSet().members(redisKey) != null; | ||
| 118 | + } | ||
| 119 | + | ||
| 120 | + /** | ||
| 121 | + * 查询ssrc是否可用 | ||
| 122 | + * | ||
| 123 | + * @param mediaServerId | ||
| 124 | + * @param ssrc | ||
| 125 | + * @return | ||
| 126 | + */ | ||
| 127 | + public boolean checkSsrc(String mediaServerId, String ssrc) { | ||
| 128 | + String sn = ssrc.substring(1); | ||
| 129 | + String redisKey = SSRC_INFO_KEY + mediaServerId; | ||
| 130 | + return redisTemplate.opsForSet().isMember(redisKey, sn) != null; | ||
| 131 | + } | ||
| 132 | +} |
src/main/java/com/genersoft/iot/vmp/gb28181/session/SsrcConfig.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.gb28181.session; | ||
| 2 | - | ||
| 3 | -import com.genersoft.iot.vmp.utils.ConfigConst; | ||
| 4 | -import io.swagger.v3.oas.annotations.media.Schema; | ||
| 5 | - | ||
| 6 | -import java.util.ArrayList; | ||
| 7 | -import java.util.List; | ||
| 8 | -import java.util.Random; | ||
| 9 | -import java.util.Set; | ||
| 10 | - | ||
| 11 | -@Schema(description = "ssrc信息") | ||
| 12 | -public class SsrcConfig { | ||
| 13 | - | ||
| 14 | - /** | ||
| 15 | - * zlm流媒体服务器Id | ||
| 16 | - */ | ||
| 17 | - @Schema(description = "流媒体服务器Id") | ||
| 18 | - private String mediaServerId; | ||
| 19 | - | ||
| 20 | - @Schema(description = "SSRC前缀") | ||
| 21 | - private String ssrcPrefix; | ||
| 22 | - | ||
| 23 | - /** | ||
| 24 | - * zlm流媒体服务器已用会话句柄 | ||
| 25 | - */ | ||
| 26 | - @Schema(description = "zlm流媒体服务器已用会话句柄") | ||
| 27 | - private List<String> isUsed; | ||
| 28 | - | ||
| 29 | - /** | ||
| 30 | - * zlm流媒体服务器可用会话句柄 | ||
| 31 | - */ | ||
| 32 | - @Schema(description = "zlm流媒体服务器可用会话句柄") | ||
| 33 | - private List<String> notUsed; | ||
| 34 | - | ||
| 35 | - public SsrcConfig() { | ||
| 36 | - } | ||
| 37 | - | ||
| 38 | - public SsrcConfig(String mediaServerId, Set<String> usedSet, String sipDomain) { | ||
| 39 | - this.mediaServerId = mediaServerId; | ||
| 40 | - this.isUsed = new ArrayList<>(); | ||
| 41 | - this.ssrcPrefix = sipDomain.substring(3, 8); | ||
| 42 | - this.notUsed = new ArrayList<>(); | ||
| 43 | - for (int i = 1; i < ConfigConst.MAX_STRTEAM_COUNT; i++) { | ||
| 44 | - String ssrc; | ||
| 45 | - if (i < 10) { | ||
| 46 | - ssrc = "000" + i; | ||
| 47 | - } else if (i < 100) { | ||
| 48 | - ssrc = "00" + i; | ||
| 49 | - } else if (i < 1000) { | ||
| 50 | - ssrc = "0" + i; | ||
| 51 | - } else { | ||
| 52 | - ssrc = String.valueOf(i); | ||
| 53 | - } | ||
| 54 | - if (null == usedSet || !usedSet.contains(ssrc)) { | ||
| 55 | - this.notUsed.add(ssrc); | ||
| 56 | - } else { | ||
| 57 | - this.isUsed.add(ssrc); | ||
| 58 | - } | ||
| 59 | - } | ||
| 60 | - } | ||
| 61 | - | ||
| 62 | - | ||
| 63 | - /** | ||
| 64 | - * 获取视频预览的SSRC值,第一位固定为0 | ||
| 65 | - * @return ssrc | ||
| 66 | - */ | ||
| 67 | - public String getPlaySsrc() { | ||
| 68 | - return "0" + getSsrcPrefix() + getSN(); | ||
| 69 | - } | ||
| 70 | - | ||
| 71 | - /** | ||
| 72 | - * 获取录像回放的SSRC值,第一位固定为1 | ||
| 73 | - * | ||
| 74 | - */ | ||
| 75 | - public String getPlayBackSsrc() { | ||
| 76 | - return "1" + getSsrcPrefix() + getSN(); | ||
| 77 | - } | ||
| 78 | - | ||
| 79 | - /** | ||
| 80 | - * 释放ssrc,主要用完的ssrc一定要释放,否则会耗尽 | ||
| 81 | - * @param ssrc 需要重置的ssrc | ||
| 82 | - */ | ||
| 83 | - public void releaseSsrc(String ssrc) { | ||
| 84 | - if (ssrc == null) { | ||
| 85 | - return; | ||
| 86 | - } | ||
| 87 | - String sn = ssrc.substring(6); | ||
| 88 | - try { | ||
| 89 | - isUsed.remove(sn); | ||
| 90 | - notUsed.add(sn); | ||
| 91 | - }catch (NullPointerException e){ | ||
| 92 | - } | ||
| 93 | - } | ||
| 94 | - | ||
| 95 | - /** | ||
| 96 | - * 获取后四位数SN,随机数 | ||
| 97 | - * | ||
| 98 | - */ | ||
| 99 | - private String getSN() { | ||
| 100 | - String sn = null; | ||
| 101 | - int index = 0; | ||
| 102 | - if (notUsed.size() == 0) { | ||
| 103 | - throw new RuntimeException("ssrc已经用完"); | ||
| 104 | - } else if (notUsed.size() == 1) { | ||
| 105 | - sn = notUsed.get(0); | ||
| 106 | - } else { | ||
| 107 | - index = new Random().nextInt(notUsed.size() - 1); | ||
| 108 | - sn = notUsed.get(index); | ||
| 109 | - } | ||
| 110 | - notUsed.remove(index); | ||
| 111 | - isUsed.add(sn); | ||
| 112 | - return sn; | ||
| 113 | - } | ||
| 114 | - | ||
| 115 | - public String getSsrcPrefix() { | ||
| 116 | - return ssrcPrefix; | ||
| 117 | - } | ||
| 118 | - | ||
| 119 | - public String getMediaServerId() { | ||
| 120 | - return mediaServerId; | ||
| 121 | - } | ||
| 122 | - | ||
| 123 | - public void setMediaServerId(String mediaServerId) { | ||
| 124 | - this.mediaServerId = mediaServerId; | ||
| 125 | - } | ||
| 126 | - | ||
| 127 | - public void setSsrcPrefix(String ssrcPrefix) { | ||
| 128 | - this.ssrcPrefix = ssrcPrefix; | ||
| 129 | - } | ||
| 130 | - | ||
| 131 | - public List<String> getIsUsed() { | ||
| 132 | - return isUsed; | ||
| 133 | - } | ||
| 134 | - | ||
| 135 | - public void setIsUsed(List<String> isUsed) { | ||
| 136 | - this.isUsed = isUsed; | ||
| 137 | - } | ||
| 138 | - | ||
| 139 | - public List<String> getNotUsed() { | ||
| 140 | - return notUsed; | ||
| 141 | - } | ||
| 142 | - | ||
| 143 | - public void setNotUsed(List<String> notUsed) { | ||
| 144 | - this.notUsed = notUsed; | ||
| 145 | - } | ||
| 146 | - | ||
| 147 | - public boolean checkSsrc(String ssrcInResponse) { | ||
| 148 | - return !isUsed.contains(ssrcInResponse); | ||
| 149 | - } | ||
| 150 | -} |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
| @@ -5,7 +5,7 @@ import com.genersoft.iot.vmp.conf.DynamicTask; | @@ -5,7 +5,7 @@ import com.genersoft.iot.vmp.conf.DynamicTask; | ||
| 5 | import com.genersoft.iot.vmp.conf.UserSetting; | 5 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 6 | import com.genersoft.iot.vmp.gb28181.bean.*; | 6 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 7 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | 7 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| 8 | -import com.genersoft.iot.vmp.gb28181.session.SsrcConfig; | 8 | +import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; |
| 9 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | 9 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 10 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; | 10 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
| 11 | import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; | 11 | import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; |
| @@ -75,6 +75,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -75,6 +75,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 75 | private IRedisCatchStorage redisCatchStorage; | 75 | private IRedisCatchStorage redisCatchStorage; |
| 76 | 76 | ||
| 77 | @Autowired | 77 | @Autowired |
| 78 | + private SSRCFactory ssrcFactory; | ||
| 79 | + | ||
| 80 | + @Autowired | ||
| 78 | private DynamicTask dynamicTask; | 81 | private DynamicTask dynamicTask; |
| 79 | 82 | ||
| 80 | @Autowired | 83 | @Autowired |
| @@ -491,12 +494,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -491,12 +494,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 491 | } else if (gbStream != null) { | 494 | } else if (gbStream != null) { |
| 492 | if(ssrc.equals(ssrcDefault)) | 495 | if(ssrc.equals(ssrcDefault)) |
| 493 | { | 496 | { |
| 494 | - SsrcConfig ssrcConfig = mediaServerItem.getSsrcConfig(); | ||
| 495 | - if(ssrcConfig != null) | ||
| 496 | - { | ||
| 497 | - ssrc = ssrcConfig.getPlaySsrc(); | ||
| 498 | - ssrcConfig.releaseSsrc(ssrc); | ||
| 499 | - } | 497 | + ssrc = ssrcFactory.getPlaySsrc(mediaServerItem.getId()); |
| 498 | + ssrcFactory.releaseSsrc(mediaServerItem.getId(), ssrc); | ||
| 500 | } | 499 | } |
| 501 | if("push".equals(gbStream.getStreamType())) { | 500 | if("push".equals(gbStream.getStreamType())) { |
| 502 | if (streamPushItem != null && streamPushItem.isPushIng()) { | 501 | if (streamPushItem != null && streamPushItem.isPushIng()) { |
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java
| 1 | package com.genersoft.iot.vmp.media.zlm.dto; | 1 | package com.genersoft.iot.vmp.media.zlm.dto; |
| 2 | 2 | ||
| 3 | 3 | ||
| 4 | -import com.genersoft.iot.vmp.gb28181.session.SsrcConfig; | 4 | +import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; |
| 5 | import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; | 5 | import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; |
| 6 | import io.swagger.v3.oas.annotations.media.Schema; | 6 | import io.swagger.v3.oas.annotations.media.Schema; |
| 7 | import org.springframework.util.ObjectUtils; | 7 | import org.springframework.util.ObjectUtils; |
| @@ -80,8 +80,8 @@ public class MediaServerItem{ | @@ -80,8 +80,8 @@ public class MediaServerItem{ | ||
| 80 | @Schema(description = "是否是默认ZLM") | 80 | @Schema(description = "是否是默认ZLM") |
| 81 | private boolean defaultServer; | 81 | private boolean defaultServer; |
| 82 | 82 | ||
| 83 | - @Schema(description = "SSRC信息") | ||
| 84 | - private SsrcConfig ssrcConfig; | 83 | +// @Schema(description = "SSRC信息") |
| 84 | +// private SsrcConfig ssrcConfig; | ||
| 85 | 85 | ||
| 86 | @Schema(description = "当前使用到的端口") | 86 | @Schema(description = "当前使用到的端口") |
| 87 | private int currentPort; | 87 | private int currentPort; |
| @@ -92,7 +92,7 @@ public class MediaServerItem{ | @@ -92,7 +92,7 @@ public class MediaServerItem{ | ||
| 92 | * 在ApplicationCheckRunner里对mediaServerSsrcMap进行初始化 | 92 | * 在ApplicationCheckRunner里对mediaServerSsrcMap进行初始化 |
| 93 | */ | 93 | */ |
| 94 | @Schema(description = "ID") | 94 | @Schema(description = "ID") |
| 95 | - private HashMap<String, SsrcConfig> mediaServerSsrcMap; | 95 | + private HashMap<String, SSRCFactory> mediaServerSsrcMap; |
| 96 | 96 | ||
| 97 | public MediaServerItem() { | 97 | public MediaServerItem() { |
| 98 | } | 98 | } |
| @@ -279,22 +279,14 @@ public class MediaServerItem{ | @@ -279,22 +279,14 @@ public class MediaServerItem{ | ||
| 279 | this.updateTime = updateTime; | 279 | this.updateTime = updateTime; |
| 280 | } | 280 | } |
| 281 | 281 | ||
| 282 | - public HashMap<String, SsrcConfig> getMediaServerSsrcMap() { | 282 | + public HashMap<String, SSRCFactory> getMediaServerSsrcMap() { |
| 283 | return mediaServerSsrcMap; | 283 | return mediaServerSsrcMap; |
| 284 | } | 284 | } |
| 285 | 285 | ||
| 286 | - public void setMediaServerSsrcMap(HashMap<String, SsrcConfig> mediaServerSsrcMap) { | 286 | + public void setMediaServerSsrcMap(HashMap<String, SSRCFactory> mediaServerSsrcMap) { |
| 287 | this.mediaServerSsrcMap = mediaServerSsrcMap; | 287 | this.mediaServerSsrcMap = mediaServerSsrcMap; |
| 288 | } | 288 | } |
| 289 | 289 | ||
| 290 | - public SsrcConfig getSsrcConfig() { | ||
| 291 | - return ssrcConfig; | ||
| 292 | - } | ||
| 293 | - | ||
| 294 | - public void setSsrcConfig(SsrcConfig ssrcConfig) { | ||
| 295 | - this.ssrcConfig = ssrcConfig; | ||
| 296 | - } | ||
| 297 | - | ||
| 298 | public int getCurrentPort() { | 290 | public int getCurrentPort() { |
| 299 | return currentPort; | 291 | return currentPort; |
| 300 | } | 292 | } |
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java
| @@ -45,6 +45,8 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService { | @@ -45,6 +45,8 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService { | ||
| 45 | device = deviceMapper.getDeviceByDeviceId(deviceChannel.getDeviceId()); | 45 | device = deviceMapper.getDeviceByDeviceId(deviceChannel.getDeviceId()); |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | + | ||
| 49 | + | ||
| 48 | if ("WGS84".equals(device.getGeoCoordSys())) { | 50 | if ("WGS84".equals(device.getGeoCoordSys())) { |
| 49 | deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude()); | 51 | deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude()); |
| 50 | deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude()); | 52 | deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude()); |
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
| @@ -9,7 +9,7 @@ import com.genersoft.iot.vmp.conf.SipConfig; | @@ -9,7 +9,7 @@ import com.genersoft.iot.vmp.conf.SipConfig; | ||
| 9 | import com.genersoft.iot.vmp.conf.UserSetting; | 9 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 10 | import com.genersoft.iot.vmp.conf.exception.ControllerException; | 10 | import com.genersoft.iot.vmp.conf.exception.ControllerException; |
| 11 | import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | 11 | import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
| 12 | -import com.genersoft.iot.vmp.gb28181.session.SsrcConfig; | 12 | +import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; |
| 13 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | 13 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 14 | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; | 14 | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; |
| 15 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; | 15 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
| @@ -54,6 +54,9 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -54,6 +54,9 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 54 | @Autowired | 54 | @Autowired |
| 55 | private SipConfig sipConfig; | 55 | private SipConfig sipConfig; |
| 56 | 56 | ||
| 57 | + @Autowired | ||
| 58 | + private SSRCFactory ssrcFactory; | ||
| 59 | + | ||
| 57 | @Value("${server.ssl.enabled:false}") | 60 | @Value("${server.ssl.enabled:false}") |
| 58 | private boolean sslEnabled; | 61 | private boolean sslEnabled; |
| 59 | 62 | ||
| @@ -90,6 +93,7 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -90,6 +93,7 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 90 | @Autowired | 93 | @Autowired |
| 91 | private IRedisCatchStorage redisCatchStorage; | 94 | private IRedisCatchStorage redisCatchStorage; |
| 92 | 95 | ||
| 96 | + | ||
| 93 | /** | 97 | /** |
| 94 | * 初始化 | 98 | * 初始化 |
| 95 | */ | 99 | */ |
| @@ -101,9 +105,8 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -101,9 +105,8 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 101 | continue; | 105 | continue; |
| 102 | } | 106 | } |
| 103 | // 更新 | 107 | // 更新 |
| 104 | - if (mediaServerItem.getSsrcConfig() == null) { | ||
| 105 | - SsrcConfig ssrcConfig = new SsrcConfig(mediaServerItem.getId(), null, sipConfig.getDomain()); | ||
| 106 | - mediaServerItem.setSsrcConfig(ssrcConfig); | 108 | + if (ssrcFactory.hasMediaServerSSRC(mediaServerItem.getId())) { |
| 109 | + ssrcFactory.initMediaServerSSRC(mediaServerItem.getId(), null); | ||
| 107 | RedisUtil.set(VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(), mediaServerItem); | 110 | RedisUtil.set(VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(), mediaServerItem); |
| 108 | } | 111 | } |
| 109 | // 查询redis是否存在此mediaServer | 112 | // 查询redis是否存在此mediaServer |
| @@ -127,36 +130,27 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -127,36 +130,27 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 127 | return null; | 130 | return null; |
| 128 | } | 131 | } |
| 129 | // 获取mediaServer可用的ssrc | 132 | // 获取mediaServer可用的ssrc |
| 130 | - String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(); | ||
| 131 | - | ||
| 132 | - SsrcConfig ssrcConfig = mediaServerItem.getSsrcConfig(); | ||
| 133 | - if (ssrcConfig == null) { | ||
| 134 | - logger.info("media server [ {} ] ssrcConfig is null", mediaServerItem.getId()); | ||
| 135 | - return null; | 133 | + String ssrc; |
| 134 | + if (presetSsrc != null) { | ||
| 135 | + ssrc = presetSsrc; | ||
| 136 | }else { | 136 | }else { |
| 137 | - String ssrc; | ||
| 138 | - if (presetSsrc != null) { | ||
| 139 | - ssrc = presetSsrc; | 137 | + if (isPlayback) { |
| 138 | + ssrc = ssrcFactory.getPlayBackSsrc(mediaServerItem.getId()); | ||
| 140 | }else { | 139 | }else { |
| 141 | - if (isPlayback) { | ||
| 142 | - ssrc = ssrcConfig.getPlayBackSsrc(); | ||
| 143 | - }else { | ||
| 144 | - ssrc = ssrcConfig.getPlaySsrc(); | ||
| 145 | - } | 140 | + ssrc = ssrcFactory.getPlaySsrc(mediaServerItem.getId()); |
| 146 | } | 141 | } |
| 142 | + } | ||
| 147 | 143 | ||
| 148 | - if (streamId == null) { | ||
| 149 | - streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase(); | ||
| 150 | - } | ||
| 151 | - int rtpServerPort; | ||
| 152 | - if (mediaServerItem.isRtpEnable()) { | ||
| 153 | - rtpServerPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId, ssrcCheck?Integer.parseInt(ssrc):0, port); | ||
| 154 | - } else { | ||
| 155 | - rtpServerPort = mediaServerItem.getRtpProxyPort(); | ||
| 156 | - } | ||
| 157 | - RedisUtil.set(key, mediaServerItem); | ||
| 158 | - return new SSRCInfo(rtpServerPort, ssrc, streamId); | 144 | + if (streamId == null) { |
| 145 | + streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase(); | ||
| 146 | + } | ||
| 147 | + int rtpServerPort; | ||
| 148 | + if (mediaServerItem.isRtpEnable()) { | ||
| 149 | + rtpServerPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId, ssrcCheck?Integer.parseInt(ssrc):0, port); | ||
| 150 | + } else { | ||
| 151 | + rtpServerPort = mediaServerItem.getRtpProxyPort(); | ||
| 159 | } | 152 | } |
| 153 | + return new SSRCInfo(rtpServerPort, ssrc, streamId); | ||
| 160 | } | 154 | } |
| 161 | 155 | ||
| 162 | @Override | 156 | @Override |
| @@ -184,11 +178,7 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -184,11 +178,7 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 184 | if (mediaServerItem == null || ssrc == null) { | 178 | if (mediaServerItem == null || ssrc == null) { |
| 185 | return; | 179 | return; |
| 186 | } | 180 | } |
| 187 | - SsrcConfig ssrcConfig = mediaServerItem.getSsrcConfig(); | ||
| 188 | - ssrcConfig.releaseSsrc(ssrc); | ||
| 189 | - mediaServerItem.setSsrcConfig(ssrcConfig); | ||
| 190 | - String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(); | ||
| 191 | - RedisUtil.set(key, mediaServerItem); | 181 | + ssrcFactory.releaseSsrc(mediaServerItemId, ssrc); |
| 192 | } | 182 | } |
| 193 | 183 | ||
| 194 | /** | 184 | /** |
| @@ -196,8 +186,7 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -196,8 +186,7 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 196 | */ | 186 | */ |
| 197 | @Override | 187 | @Override |
| 198 | public void clearRTPServer(MediaServerItem mediaServerItem) { | 188 | public void clearRTPServer(MediaServerItem mediaServerItem) { |
| 199 | - mediaServerItem.setSsrcConfig(new SsrcConfig(mediaServerItem.getId(), null, sipConfig.getDomain())); | ||
| 200 | - RedisUtil.zAdd(VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId(), mediaServerItem.getId(), 0); | 189 | + ssrcFactory.reset(mediaServerItem.getId()); |
| 201 | 190 | ||
| 202 | } | 191 | } |
| 203 | 192 | ||
| @@ -207,16 +196,8 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -207,16 +196,8 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 207 | mediaServerMapper.update(mediaSerItem); | 196 | mediaServerMapper.update(mediaSerItem); |
| 208 | MediaServerItem mediaServerItemInRedis = getOne(mediaSerItem.getId()); | 197 | MediaServerItem mediaServerItemInRedis = getOne(mediaSerItem.getId()); |
| 209 | MediaServerItem mediaServerItemInDataBase = mediaServerMapper.queryOne(mediaSerItem.getId()); | 198 | MediaServerItem mediaServerItemInDataBase = mediaServerMapper.queryOne(mediaSerItem.getId()); |
| 210 | - if (mediaServerItemInRedis != null && mediaServerItemInRedis.getSsrcConfig() != null) { | ||
| 211 | - mediaServerItemInDataBase.setSsrcConfig(mediaServerItemInRedis.getSsrcConfig()); | ||
| 212 | - }else { | ||
| 213 | - mediaServerItemInDataBase.setSsrcConfig( | ||
| 214 | - new SsrcConfig( | ||
| 215 | - mediaServerItemInDataBase.getId(), | ||
| 216 | - null, | ||
| 217 | - sipConfig.getDomain() | ||
| 218 | - ) | ||
| 219 | - ); | 199 | + if (mediaServerItemInRedis == null || ssrcFactory.hasMediaServerSSRC(mediaSerItem.getId())) { |
| 200 | + ssrcFactory.initMediaServerSSRC(mediaServerItemInDataBase.getId(),null); | ||
| 220 | } | 201 | } |
| 221 | String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItemInDataBase.getId(); | 202 | String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItemInDataBase.getId(); |
| 222 | RedisUtil.set(key, mediaServerItemInDataBase); | 203 | RedisUtil.set(key, mediaServerItemInDataBase); |
| @@ -396,14 +377,8 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -396,14 +377,8 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 396 | } | 377 | } |
| 397 | mediaServerMapper.update(serverItem); | 378 | mediaServerMapper.update(serverItem); |
| 398 | String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + zlmServerConfig.getGeneralMediaServerId(); | 379 | String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + zlmServerConfig.getGeneralMediaServerId(); |
| 399 | - if (RedisUtil.get(key) == null) { | ||
| 400 | - SsrcConfig ssrcConfig = new SsrcConfig(zlmServerConfig.getGeneralMediaServerId(), null, sipConfig.getDomain()); | ||
| 401 | - serverItem.setSsrcConfig(ssrcConfig); | ||
| 402 | - }else { | ||
| 403 | - MediaServerItem mediaServerItemInRedis = JsonUtil.redisJsonToObject(key, MediaServerItem.class); | ||
| 404 | - if (Objects.nonNull(mediaServerItemInRedis)) { | ||
| 405 | - serverItem.setSsrcConfig(mediaServerItemInRedis.getSsrcConfig()); | ||
| 406 | - } | 380 | + if (ssrcFactory.hasMediaServerSSRC(serverItem.getId())) { |
| 381 | + ssrcFactory.initMediaServerSSRC(zlmServerConfig.getGeneralMediaServerId(), null); | ||
| 407 | } | 382 | } |
| 408 | RedisUtil.set(key, serverItem); | 383 | RedisUtil.set(key, serverItem); |
| 409 | resetOnlineServerItem(serverItem); | 384 | resetOnlineServerItem(serverItem); |
| @@ -682,8 +657,7 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -682,8 +657,7 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 682 | } | 657 | } |
| 683 | // zlm连接重试 | 658 | // zlm连接重试 |
| 684 | logger.warn("[更新ZLM 保活信息]尝试链接zml id {}", mediaServerId); | 659 | logger.warn("[更新ZLM 保活信息]尝试链接zml id {}", mediaServerId); |
| 685 | - SsrcConfig ssrcConfig = new SsrcConfig(mediaServerItem.getId(), null, sipConfig.getDomain()); | ||
| 686 | - mediaServerItem.setSsrcConfig(ssrcConfig); | 660 | + ssrcFactory.initMediaServerSSRC(mediaServerItem.getId(), null); |
| 687 | String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(); | 661 | String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(); |
| 688 | RedisUtil.set(key, mediaServerItem); | 662 | RedisUtil.set(key, mediaServerItem); |
| 689 | clearRTPServer(mediaServerItem); | 663 | clearRTPServer(mediaServerItem); |
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
| @@ -11,6 +11,7 @@ import com.genersoft.iot.vmp.conf.exception.ServiceException; | @@ -11,6 +11,7 @@ import com.genersoft.iot.vmp.conf.exception.ServiceException; | ||
| 11 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | 11 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; |
| 12 | import com.genersoft.iot.vmp.gb28181.bean.*; | 12 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 13 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | 13 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| 14 | +import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; | ||
| 14 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | 15 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 15 | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; | 16 | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
| 16 | import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | 17 | import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; |
| @@ -100,6 +101,9 @@ public class PlayServiceImpl implements IPlayService { | @@ -100,6 +101,9 @@ public class PlayServiceImpl implements IPlayService { | ||
| 100 | @Autowired | 101 | @Autowired |
| 101 | private ZlmHttpHookSubscribe subscribe; | 102 | private ZlmHttpHookSubscribe subscribe; |
| 102 | 103 | ||
| 104 | + @Autowired | ||
| 105 | + private SSRCFactory ssrcFactory; | ||
| 106 | + | ||
| 103 | 107 | ||
| 104 | @Override | 108 | @Override |
| 105 | public void play(MediaServerItem mediaServerItem, String deviceId, String channelId, | 109 | public void play(MediaServerItem mediaServerItem, String deviceId, String channelId, |
| @@ -295,10 +299,10 @@ public class PlayServiceImpl implements IPlayService { | @@ -295,10 +299,10 @@ public class PlayServiceImpl implements IPlayService { | ||
| 295 | if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { | 299 | if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { |
| 296 | logger.info("[点播消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); | 300 | logger.info("[点播消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); |
| 297 | 301 | ||
| 298 | - if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) { | 302 | + if (!ssrcFactory.checkSsrc(mediaServerItem.getId(),ssrcInResponse)) { |
| 299 | // ssrc 不可用 | 303 | // ssrc 不可用 |
| 300 | // 释放ssrc | 304 | // 释放ssrc |
| 301 | - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | 305 | + ssrcFactory.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); |
| 302 | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); | 306 | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); |
| 303 | event.msg = "下级自定义了ssrc,但是此ssrc不可用"; | 307 | event.msg = "下级自定义了ssrc,但是此ssrc不可用"; |
| 304 | event.statusCode = 400; | 308 | event.statusCode = 400; |
| @@ -536,7 +540,7 @@ public class PlayServiceImpl implements IPlayService { | @@ -536,7 +540,7 @@ public class PlayServiceImpl implements IPlayService { | ||
| 536 | if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { | 540 | if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { |
| 537 | logger.info("[回放消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); | 541 | logger.info("[回放消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); |
| 538 | 542 | ||
| 539 | - if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) { | 543 | + if (!ssrcFactory.checkSsrc(mediaServerItem.getId(),ssrcInResponse)) { |
| 540 | // ssrc 不可用 | 544 | // ssrc 不可用 |
| 541 | // 释放ssrc | 545 | // 释放ssrc |
| 542 | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | 546 | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); |
| @@ -675,7 +679,7 @@ public class PlayServiceImpl implements IPlayService { | @@ -675,7 +679,7 @@ public class PlayServiceImpl implements IPlayService { | ||
| 675 | if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { | 679 | if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { |
| 676 | logger.info("[回放消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); | 680 | logger.info("[回放消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); |
| 677 | 681 | ||
| 678 | - if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) { | 682 | + if (!ssrcFactory.checkSsrc(mediaServerItem.getId(),ssrcInResponse)) { |
| 679 | // ssrc 不可用 | 683 | // ssrc 不可用 |
| 680 | // 释放ssrc | 684 | // 释放ssrc |
| 681 | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | 685 | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); |