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 | 9 | import org.springframework.context.annotation.Configuration; |
| 10 | 10 | import org.springframework.core.annotation.Order; |
| 11 | 11 | import org.springframework.data.redis.connection.RedisConnectionFactory; |
| 12 | -import org.springframework.data.redis.core.RedisTemplate; | |
| 13 | 12 | import org.springframework.data.redis.listener.PatternTopic; |
| 14 | 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 | 44 | @Autowired |
| 49 | 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 | 5 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 6 | 6 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 7 | 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 | 9 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 10 | 10 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
| 11 | 11 | import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; |
| ... | ... | @@ -75,6 +75,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 75 | 75 | private IRedisCatchStorage redisCatchStorage; |
| 76 | 76 | |
| 77 | 77 | @Autowired |
| 78 | + private SSRCFactory ssrcFactory; | |
| 79 | + | |
| 80 | + @Autowired | |
| 78 | 81 | private DynamicTask dynamicTask; |
| 79 | 82 | |
| 80 | 83 | @Autowired |
| ... | ... | @@ -491,12 +494,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 491 | 494 | } else if (gbStream != null) { |
| 492 | 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 | 500 | if("push".equals(gbStream.getStreamType())) { |
| 502 | 501 | if (streamPushItem != null && streamPushItem.isPushIng()) { | ... | ... |
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java
| 1 | 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 | 5 | import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; |
| 6 | 6 | import io.swagger.v3.oas.annotations.media.Schema; |
| 7 | 7 | import org.springframework.util.ObjectUtils; |
| ... | ... | @@ -80,8 +80,8 @@ public class MediaServerItem{ |
| 80 | 80 | @Schema(description = "是否是默认ZLM") |
| 81 | 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 | 86 | @Schema(description = "当前使用到的端口") |
| 87 | 87 | private int currentPort; |
| ... | ... | @@ -92,7 +92,7 @@ public class MediaServerItem{ |
| 92 | 92 | * 在ApplicationCheckRunner里对mediaServerSsrcMap进行初始化 |
| 93 | 93 | */ |
| 94 | 94 | @Schema(description = "ID") |
| 95 | - private HashMap<String, SsrcConfig> mediaServerSsrcMap; | |
| 95 | + private HashMap<String, SSRCFactory> mediaServerSsrcMap; | |
| 96 | 96 | |
| 97 | 97 | public MediaServerItem() { |
| 98 | 98 | } |
| ... | ... | @@ -279,22 +279,14 @@ public class MediaServerItem{ |
| 279 | 279 | this.updateTime = updateTime; |
| 280 | 280 | } |
| 281 | 281 | |
| 282 | - public HashMap<String, SsrcConfig> getMediaServerSsrcMap() { | |
| 282 | + public HashMap<String, SSRCFactory> getMediaServerSsrcMap() { | |
| 283 | 283 | return mediaServerSsrcMap; |
| 284 | 284 | } |
| 285 | 285 | |
| 286 | - public void setMediaServerSsrcMap(HashMap<String, SsrcConfig> mediaServerSsrcMap) { | |
| 286 | + public void setMediaServerSsrcMap(HashMap<String, SSRCFactory> mediaServerSsrcMap) { | |
| 287 | 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 | 290 | public int getCurrentPort() { |
| 299 | 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 | 45 | device = deviceMapper.getDeviceByDeviceId(deviceChannel.getDeviceId()); |
| 46 | 46 | } |
| 47 | 47 | |
| 48 | + | |
| 49 | + | |
| 48 | 50 | if ("WGS84".equals(device.getGeoCoordSys())) { |
| 49 | 51 | deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude()); |
| 50 | 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 | 9 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 10 | 10 | import com.genersoft.iot.vmp.conf.exception.ControllerException; |
| 11 | 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 | 13 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 14 | 14 | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; |
| 15 | 15 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
| ... | ... | @@ -54,6 +54,9 @@ public class MediaServerServiceImpl implements IMediaServerService { |
| 54 | 54 | @Autowired |
| 55 | 55 | private SipConfig sipConfig; |
| 56 | 56 | |
| 57 | + @Autowired | |
| 58 | + private SSRCFactory ssrcFactory; | |
| 59 | + | |
| 57 | 60 | @Value("${server.ssl.enabled:false}") |
| 58 | 61 | private boolean sslEnabled; |
| 59 | 62 | |
| ... | ... | @@ -90,6 +93,7 @@ public class MediaServerServiceImpl implements IMediaServerService { |
| 90 | 93 | @Autowired |
| 91 | 94 | private IRedisCatchStorage redisCatchStorage; |
| 92 | 95 | |
| 96 | + | |
| 93 | 97 | /** |
| 94 | 98 | * 初始化 |
| 95 | 99 | */ |
| ... | ... | @@ -101,9 +105,8 @@ public class MediaServerServiceImpl implements IMediaServerService { |
| 101 | 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 | 110 | RedisUtil.set(VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(), mediaServerItem); |
| 108 | 111 | } |
| 109 | 112 | // 查询redis是否存在此mediaServer |
| ... | ... | @@ -127,36 +130,27 @@ public class MediaServerServiceImpl implements IMediaServerService { |
| 127 | 130 | return null; |
| 128 | 131 | } |
| 129 | 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 | 136 | }else { |
| 137 | - String ssrc; | |
| 138 | - if (presetSsrc != null) { | |
| 139 | - ssrc = presetSsrc; | |
| 137 | + if (isPlayback) { | |
| 138 | + ssrc = ssrcFactory.getPlayBackSsrc(mediaServerItem.getId()); | |
| 140 | 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 | 156 | @Override |
| ... | ... | @@ -184,11 +178,7 @@ public class MediaServerServiceImpl implements IMediaServerService { |
| 184 | 178 | if (mediaServerItem == null || ssrc == null) { |
| 185 | 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 | 186 | */ |
| 197 | 187 | @Override |
| 198 | 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 | 196 | mediaServerMapper.update(mediaSerItem); |
| 208 | 197 | MediaServerItem mediaServerItemInRedis = getOne(mediaSerItem.getId()); |
| 209 | 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 | 202 | String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItemInDataBase.getId(); |
| 222 | 203 | RedisUtil.set(key, mediaServerItemInDataBase); |
| ... | ... | @@ -396,14 +377,8 @@ public class MediaServerServiceImpl implements IMediaServerService { |
| 396 | 377 | } |
| 397 | 378 | mediaServerMapper.update(serverItem); |
| 398 | 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 | 383 | RedisUtil.set(key, serverItem); |
| 409 | 384 | resetOnlineServerItem(serverItem); |
| ... | ... | @@ -682,8 +657,7 @@ public class MediaServerServiceImpl implements IMediaServerService { |
| 682 | 657 | } |
| 683 | 658 | // zlm连接重试 |
| 684 | 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 | 661 | String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(); |
| 688 | 662 | RedisUtil.set(key, mediaServerItem); |
| 689 | 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 | 11 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; |
| 12 | 12 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 13 | 13 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| 14 | +import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; | |
| 14 | 15 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 15 | 16 | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
| 16 | 17 | import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; |
| ... | ... | @@ -100,6 +101,9 @@ public class PlayServiceImpl implements IPlayService { |
| 100 | 101 | @Autowired |
| 101 | 102 | private ZlmHttpHookSubscribe subscribe; |
| 102 | 103 | |
| 104 | + @Autowired | |
| 105 | + private SSRCFactory ssrcFactory; | |
| 106 | + | |
| 103 | 107 | |
| 104 | 108 | @Override |
| 105 | 109 | public void play(MediaServerItem mediaServerItem, String deviceId, String channelId, |
| ... | ... | @@ -295,10 +299,10 @@ public class PlayServiceImpl implements IPlayService { |
| 295 | 299 | if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { |
| 296 | 300 | logger.info("[点播消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); |
| 297 | 301 | |
| 298 | - if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) { | |
| 302 | + if (!ssrcFactory.checkSsrc(mediaServerItem.getId(),ssrcInResponse)) { | |
| 299 | 303 | // ssrc 不可用 |
| 300 | 304 | // 释放ssrc |
| 301 | - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | |
| 305 | + ssrcFactory.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | |
| 302 | 306 | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); |
| 303 | 307 | event.msg = "下级自定义了ssrc,但是此ssrc不可用"; |
| 304 | 308 | event.statusCode = 400; |
| ... | ... | @@ -536,7 +540,7 @@ public class PlayServiceImpl implements IPlayService { |
| 536 | 540 | if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { |
| 537 | 541 | logger.info("[回放消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); |
| 538 | 542 | |
| 539 | - if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) { | |
| 543 | + if (!ssrcFactory.checkSsrc(mediaServerItem.getId(),ssrcInResponse)) { | |
| 540 | 544 | // ssrc 不可用 |
| 541 | 545 | // 释放ssrc |
| 542 | 546 | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); |
| ... | ... | @@ -675,7 +679,7 @@ public class PlayServiceImpl implements IPlayService { |
| 675 | 679 | if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { |
| 676 | 680 | logger.info("[回放消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); |
| 677 | 681 | |
| 678 | - if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) { | |
| 682 | + if (!ssrcFactory.checkSsrc(mediaServerItem.getId(),ssrcInResponse)) { | |
| 679 | 683 | // ssrc 不可用 |
| 680 | 684 | // 释放ssrc |
| 681 | 685 | mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | ... | ... |