Merge branch '2.6.7' into wvp-28181-2.0
# Conflicts: # src/main/java/com/genersoft/iot/vmp/conf/redis/RedisConfig.java # src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java # src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.javapull/817/head
commit
8c4922cbe1
|
@ -9,6 +9,9 @@ import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||||
|
|
||||||
|
import org.springframework.data.redis.listener.PatternTopic;
|
||||||
|
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Redis中间件配置类,使用spring-data-redis集成,自动从application.yml中加载redis配置
|
* Redis中间件配置类,使用spring-data-redis集成,自动从application.yml中加载redis配置
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.genersoft.iot.vmp.conf.redis;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.utils.redis.FastJsonRedisSerializer;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class RedisTemplateConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
|
||||||
|
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
|
||||||
|
// 使用fastJson序列化
|
||||||
|
FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
|
||||||
|
// value值的序列化采用fastJsonRedisSerializer
|
||||||
|
redisTemplate.setValueSerializer(fastJsonRedisSerializer);
|
||||||
|
redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
|
||||||
|
|
||||||
|
// key的序列化采用StringRedisSerializer
|
||||||
|
redisTemplate.setKeySerializer(new StringRedisSerializer());
|
||||||
|
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
|
||||||
|
redisTemplate.setConnectionFactory(redisConnectionFactory);
|
||||||
|
return redisTemplate;
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,7 +38,6 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!userSetting.isInterfaceAuthentication()) {
|
if (!userSetting.isInterfaceAuthentication()) {
|
||||||
// 构建UsernamePasswordAuthenticationToken,这里密码为null,是因为提供了正确的JWT,实现自动登录
|
|
||||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(null, null, new ArrayList<>() );
|
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(null, null, new ArrayList<>() );
|
||||||
SecurityContextHolder.getContext().setAuthentication(token);
|
SecurityContextHolder.getContext().setAuthentication(token);
|
||||||
chain.doFilter(request, response);
|
chain.doFilter(request, response);
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
package com.genersoft.iot.vmp.gb28181.session;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ssrc使用
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class SSRCFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 播流最大并发个数
|
||||||
|
*/
|
||||||
|
private static final Integer MAX_STREAM_COUNT = 10000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 播流最大并发个数
|
||||||
|
*/
|
||||||
|
private static final String SSRC_INFO_KEY = "VMP_SSRC_INFO_";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private StringRedisTemplate redisTemplate;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SipConfig sipConfig;
|
||||||
|
|
||||||
|
|
||||||
|
public void initMediaServerSSRC(String mediaServerId, Set<String> usedSet) {
|
||||||
|
String ssrcPrefix = sipConfig.getDomain().substring(3, 8);
|
||||||
|
String redisKey = SSRC_INFO_KEY + mediaServerId;
|
||||||
|
List<String> ssrcList = new ArrayList<>();
|
||||||
|
for (int i = 1; i < MAX_STREAM_COUNT; i++) {
|
||||||
|
String ssrc = String.format("%s%04d", ssrcPrefix, i);
|
||||||
|
|
||||||
|
if (null == usedSet || !usedSet.contains(ssrc)) {
|
||||||
|
ssrcList.add(ssrc);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (redisTemplate.opsForSet().size(redisKey) != null) {
|
||||||
|
redisTemplate.delete(redisKey);
|
||||||
|
}
|
||||||
|
redisTemplate.opsForSet().add(redisKey, ssrcList.toArray(new String[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取视频预览的SSRC值,第一位固定为0
|
||||||
|
*
|
||||||
|
* @return ssrc
|
||||||
|
*/
|
||||||
|
public String getPlaySsrc(String mediaServerId) {
|
||||||
|
return "0" + getSN(mediaServerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取录像回放的SSRC值,第一位固定为1
|
||||||
|
*/
|
||||||
|
public String getPlayBackSsrc(String mediaServerId) {
|
||||||
|
return "1" + getSN(mediaServerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 释放ssrc,主要用完的ssrc一定要释放,否则会耗尽
|
||||||
|
*
|
||||||
|
* @param ssrc 需要重置的ssrc
|
||||||
|
*/
|
||||||
|
public void releaseSsrc(String mediaServerId, String ssrc) {
|
||||||
|
if (ssrc == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String sn = ssrc.substring(1);
|
||||||
|
String redisKey = SSRC_INFO_KEY + mediaServerId;
|
||||||
|
redisTemplate.opsForSet().add(redisKey, sn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取后四位数SN,随机数
|
||||||
|
*/
|
||||||
|
private String getSN(String mediaServerId) {
|
||||||
|
String sn = null;
|
||||||
|
String redisKey = SSRC_INFO_KEY + mediaServerId;
|
||||||
|
Long size = redisTemplate.opsForSet().size(redisKey);
|
||||||
|
if (size == null || size == 0) {
|
||||||
|
throw new RuntimeException("ssrc已经用完");
|
||||||
|
} else {
|
||||||
|
// 在集合中移除并返回一个随机成员。
|
||||||
|
sn = (String) redisTemplate.opsForSet().pop(redisKey);
|
||||||
|
redisTemplate.opsForSet().remove(redisKey, sn);
|
||||||
|
}
|
||||||
|
return sn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置一个流媒体服务的所有ssrc
|
||||||
|
*
|
||||||
|
* @param mediaServerId 流媒体服务ID
|
||||||
|
*/
|
||||||
|
public void reset(String mediaServerId) {
|
||||||
|
this.initMediaServerSSRC(mediaServerId, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否已经存在了某个MediaServer的SSRC信息
|
||||||
|
*
|
||||||
|
* @param mediaServerId 流媒体服务ID
|
||||||
|
*/
|
||||||
|
public boolean hasMediaServerSSRC(String mediaServerId) {
|
||||||
|
String redisKey = SSRC_INFO_KEY + mediaServerId;
|
||||||
|
return redisTemplate.opsForSet().members(redisKey) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询ssrc是否可用
|
||||||
|
*
|
||||||
|
* @param mediaServerId
|
||||||
|
* @param ssrc
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean checkSsrc(String mediaServerId, String ssrc) {
|
||||||
|
String sn = ssrc.substring(1);
|
||||||
|
String redisKey = SSRC_INFO_KEY + mediaServerId;
|
||||||
|
return redisTemplate.opsForSet().isMember(redisKey, sn) != null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,150 +0,0 @@
|
||||||
package com.genersoft.iot.vmp.gb28181.session;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.utils.ConfigConst;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Random;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
@Schema(description = "ssrc信息")
|
|
||||||
public class SsrcConfig {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* zlm流媒体服务器Id
|
|
||||||
*/
|
|
||||||
@Schema(description = "流媒体服务器Id")
|
|
||||||
private String mediaServerId;
|
|
||||||
|
|
||||||
@Schema(description = "SSRC前缀")
|
|
||||||
private String ssrcPrefix;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* zlm流媒体服务器已用会话句柄
|
|
||||||
*/
|
|
||||||
@Schema(description = "zlm流媒体服务器已用会话句柄")
|
|
||||||
private List<String> isUsed;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* zlm流媒体服务器可用会话句柄
|
|
||||||
*/
|
|
||||||
@Schema(description = "zlm流媒体服务器可用会话句柄")
|
|
||||||
private List<String> notUsed;
|
|
||||||
|
|
||||||
public SsrcConfig() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public SsrcConfig(String mediaServerId, Set<String> usedSet, String sipDomain) {
|
|
||||||
this.mediaServerId = mediaServerId;
|
|
||||||
this.isUsed = new ArrayList<>();
|
|
||||||
this.ssrcPrefix = sipDomain.substring(3, 8);
|
|
||||||
this.notUsed = new ArrayList<>();
|
|
||||||
for (int i = 1; i < ConfigConst.MAX_STRTEAM_COUNT; i++) {
|
|
||||||
String ssrc;
|
|
||||||
if (i < 10) {
|
|
||||||
ssrc = "000" + i;
|
|
||||||
} else if (i < 100) {
|
|
||||||
ssrc = "00" + i;
|
|
||||||
} else if (i < 1000) {
|
|
||||||
ssrc = "0" + i;
|
|
||||||
} else {
|
|
||||||
ssrc = String.valueOf(i);
|
|
||||||
}
|
|
||||||
if (null == usedSet || !usedSet.contains(ssrc)) {
|
|
||||||
this.notUsed.add(ssrc);
|
|
||||||
} else {
|
|
||||||
this.isUsed.add(ssrc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取视频预览的SSRC值,第一位固定为0
|
|
||||||
* @return ssrc
|
|
||||||
*/
|
|
||||||
public String getPlaySsrc() {
|
|
||||||
return "0" + getSsrcPrefix() + getSN();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取录像回放的SSRC值,第一位固定为1
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public String getPlayBackSsrc() {
|
|
||||||
return "1" + getSsrcPrefix() + getSN();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 释放ssrc,主要用完的ssrc一定要释放,否则会耗尽
|
|
||||||
* @param ssrc 需要重置的ssrc
|
|
||||||
*/
|
|
||||||
public void releaseSsrc(String ssrc) {
|
|
||||||
if (ssrc == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String sn = ssrc.substring(6);
|
|
||||||
try {
|
|
||||||
isUsed.remove(sn);
|
|
||||||
notUsed.add(sn);
|
|
||||||
}catch (NullPointerException e){
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取后四位数SN,随机数
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private String getSN() {
|
|
||||||
String sn = null;
|
|
||||||
int index = 0;
|
|
||||||
if (notUsed.size() == 0) {
|
|
||||||
throw new RuntimeException("ssrc已经用完");
|
|
||||||
} else if (notUsed.size() == 1) {
|
|
||||||
sn = notUsed.get(0);
|
|
||||||
} else {
|
|
||||||
index = new Random().nextInt(notUsed.size() - 1);
|
|
||||||
sn = notUsed.get(index);
|
|
||||||
}
|
|
||||||
notUsed.remove(index);
|
|
||||||
isUsed.add(sn);
|
|
||||||
return sn;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSsrcPrefix() {
|
|
||||||
return ssrcPrefix;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMediaServerId() {
|
|
||||||
return mediaServerId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMediaServerId(String mediaServerId) {
|
|
||||||
this.mediaServerId = mediaServerId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSsrcPrefix(String ssrcPrefix) {
|
|
||||||
this.ssrcPrefix = ssrcPrefix;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getIsUsed() {
|
|
||||||
return isUsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIsUsed(List<String> isUsed) {
|
|
||||||
this.isUsed = isUsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getNotUsed() {
|
|
||||||
return notUsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNotUsed(List<String> notUsed) {
|
|
||||||
this.notUsed = notUsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean checkSsrc(String ssrcInResponse) {
|
|
||||||
return !isUsed.contains(ssrcInResponse);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,7 +5,7 @@ import com.genersoft.iot.vmp.conf.DynamicTask;
|
||||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
import com.genersoft.iot.vmp.gb28181.session.SsrcConfig;
|
import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
|
||||||
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.SIPSender;
|
import com.genersoft.iot.vmp.gb28181.transmit.SIPSender;
|
||||||
|
@ -74,6 +74,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||||
@Autowired
|
@Autowired
|
||||||
private IRedisCatchStorage redisCatchStorage;
|
private IRedisCatchStorage redisCatchStorage;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SSRCFactory ssrcFactory;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DynamicTask dynamicTask;
|
private DynamicTask dynamicTask;
|
||||||
|
|
||||||
|
@ -491,12 +494,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||||
} else if (gbStream != null) {
|
} else if (gbStream != null) {
|
||||||
if(ssrc.equals(ssrcDefault))
|
if(ssrc.equals(ssrcDefault))
|
||||||
{
|
{
|
||||||
SsrcConfig ssrcConfig = mediaServerItem.getSsrcConfig();
|
ssrc = ssrcFactory.getPlaySsrc(mediaServerItem.getId());
|
||||||
if(ssrcConfig != null)
|
ssrcFactory.releaseSsrc(mediaServerItem.getId(), ssrc);
|
||||||
{
|
|
||||||
ssrc = ssrcConfig.getPlaySsrc();
|
|
||||||
ssrcConfig.releaseSsrc(ssrc);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if("push".equals(gbStream.getStreamType())) {
|
if("push".equals(gbStream.getStreamType())) {
|
||||||
if (streamPushItem != null && streamPushItem.isPushIng()) {
|
if (streamPushItem != null && streamPushItem.isPushIng()) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package com.genersoft.iot.vmp.media.zlm.dto;
|
package com.genersoft.iot.vmp.media.zlm.dto;
|
||||||
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.gb28181.session.SsrcConfig;
|
import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
|
import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
|
@ -80,8 +80,8 @@ public class MediaServerItem{
|
||||||
@Schema(description = "是否是默认ZLM")
|
@Schema(description = "是否是默认ZLM")
|
||||||
private boolean defaultServer;
|
private boolean defaultServer;
|
||||||
|
|
||||||
@Schema(description = "SSRC信息")
|
// @Schema(description = "SSRC信息")
|
||||||
private SsrcConfig ssrcConfig;
|
// private SsrcConfig ssrcConfig;
|
||||||
|
|
||||||
@Schema(description = "当前使用到的端口")
|
@Schema(description = "当前使用到的端口")
|
||||||
private int currentPort;
|
private int currentPort;
|
||||||
|
@ -92,7 +92,7 @@ public class MediaServerItem{
|
||||||
* 在ApplicationCheckRunner里对mediaServerSsrcMap进行初始化
|
* 在ApplicationCheckRunner里对mediaServerSsrcMap进行初始化
|
||||||
*/
|
*/
|
||||||
@Schema(description = "ID")
|
@Schema(description = "ID")
|
||||||
private HashMap<String, SsrcConfig> mediaServerSsrcMap;
|
private HashMap<String, SSRCFactory> mediaServerSsrcMap;
|
||||||
|
|
||||||
public MediaServerItem() {
|
public MediaServerItem() {
|
||||||
}
|
}
|
||||||
|
@ -279,22 +279,14 @@ public class MediaServerItem{
|
||||||
this.updateTime = updateTime;
|
this.updateTime = updateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HashMap<String, SsrcConfig> getMediaServerSsrcMap() {
|
public HashMap<String, SSRCFactory> getMediaServerSsrcMap() {
|
||||||
return mediaServerSsrcMap;
|
return mediaServerSsrcMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMediaServerSsrcMap(HashMap<String, SsrcConfig> mediaServerSsrcMap) {
|
public void setMediaServerSsrcMap(HashMap<String, SSRCFactory> mediaServerSsrcMap) {
|
||||||
this.mediaServerSsrcMap = mediaServerSsrcMap;
|
this.mediaServerSsrcMap = mediaServerSsrcMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SsrcConfig getSsrcConfig() {
|
|
||||||
return ssrcConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSsrcConfig(SsrcConfig ssrcConfig) {
|
|
||||||
this.ssrcConfig = ssrcConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getCurrentPort() {
|
public int getCurrentPort() {
|
||||||
return currentPort;
|
return currentPort;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,8 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
|
||||||
device = deviceMapper.getDeviceByDeviceId(deviceChannel.getDeviceId());
|
device = deviceMapper.getDeviceByDeviceId(deviceChannel.getDeviceId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if ("WGS84".equals(device.getGeoCoordSys())) {
|
if ("WGS84".equals(device.getGeoCoordSys())) {
|
||||||
deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude());
|
deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude());
|
||||||
deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude());
|
deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude());
|
||||||
|
|
|
@ -9,6 +9,8 @@ import com.genersoft.iot.vmp.conf.SipConfig;
|
||||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||||
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||||
import com.genersoft.iot.vmp.gb28181.session.SsrcConfig;
|
import com.genersoft.iot.vmp.gb28181.session.SsrcConfig;
|
||||||
import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;
|
import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
||||||
|
@ -56,6 +58,9 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||||
@Autowired
|
@Autowired
|
||||||
private SipConfig sipConfig;
|
private SipConfig sipConfig;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SSRCFactory ssrcFactory;
|
||||||
|
|
||||||
@Value("${server.ssl.enabled:false}")
|
@Value("${server.ssl.enabled:false}")
|
||||||
private boolean sslEnabled;
|
private boolean sslEnabled;
|
||||||
|
|
||||||
|
@ -96,6 +101,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedisTemplate<Object, Object> redisTemplate;
|
private RedisTemplate<Object, Object> redisTemplate;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化
|
* 初始化
|
||||||
*/
|
*/
|
||||||
|
@ -107,10 +113,8 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// 更新
|
// 更新
|
||||||
if (mediaServerItem.getSsrcConfig() == null) {
|
if (ssrcFactory.hasMediaServerSSRC(mediaServerItem.getId())) {
|
||||||
SsrcConfig ssrcConfig = new SsrcConfig(mediaServerItem.getId(), null, sipConfig.getDomain());
|
ssrcFactory.initMediaServerSSRC(mediaServerItem.getId(), null);
|
||||||
mediaServerItem.setSsrcConfig(ssrcConfig);
|
|
||||||
redisTemplate.opsForValue().set(VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(), mediaServerItem);
|
|
||||||
}
|
}
|
||||||
// 查询redis是否存在此mediaServer
|
// 查询redis是否存在此mediaServer
|
||||||
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId();
|
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId();
|
||||||
|
@ -134,21 +138,14 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// 获取mediaServer可用的ssrc
|
// 获取mediaServer可用的ssrc
|
||||||
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId();
|
|
||||||
|
|
||||||
SsrcConfig ssrcConfig = mediaServerItem.getSsrcConfig();
|
|
||||||
if (ssrcConfig == null) {
|
|
||||||
logger.info("media server [ {} ] ssrcConfig is null", mediaServerItem.getId());
|
|
||||||
return null;
|
|
||||||
}else {
|
|
||||||
String ssrc;
|
String ssrc;
|
||||||
if (presetSsrc != null) {
|
if (presetSsrc != null) {
|
||||||
ssrc = presetSsrc;
|
ssrc = presetSsrc;
|
||||||
}else {
|
}else {
|
||||||
if (isPlayback) {
|
if (isPlayback) {
|
||||||
ssrc = ssrcConfig.getPlayBackSsrc();
|
ssrc = ssrcFactory.getPlayBackSsrc(mediaServerItem.getId());
|
||||||
}else {
|
}else {
|
||||||
ssrc = ssrcConfig.getPlaySsrc();
|
ssrc = ssrcFactory.getPlaySsrc(mediaServerItem.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,10 +158,8 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||||
} else {
|
} else {
|
||||||
rtpServerPort = mediaServerItem.getRtpProxyPort();
|
rtpServerPort = mediaServerItem.getRtpProxyPort();
|
||||||
}
|
}
|
||||||
redisTemplate.opsForValue().set(key, mediaServerItem);
|
|
||||||
return new SSRCInfo(rtpServerPort, ssrc, streamId);
|
return new SSRCInfo(rtpServerPort, ssrc, streamId);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback) {
|
public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback) {
|
||||||
|
@ -191,11 +186,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||||
if (mediaServerItem == null || ssrc == null) {
|
if (mediaServerItem == null || ssrc == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SsrcConfig ssrcConfig = mediaServerItem.getSsrcConfig();
|
ssrcFactory.releaseSsrc(mediaServerItemId, ssrc);
|
||||||
ssrcConfig.releaseSsrc(ssrc);
|
|
||||||
mediaServerItem.setSsrcConfig(ssrcConfig);
|
|
||||||
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId();
|
|
||||||
redisTemplate.opsForValue().set(key, mediaServerItem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -203,8 +194,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void clearRTPServer(MediaServerItem mediaServerItem) {
|
public void clearRTPServer(MediaServerItem mediaServerItem) {
|
||||||
mediaServerItem.setSsrcConfig(new SsrcConfig(mediaServerItem.getId(), null, sipConfig.getDomain()));
|
ssrcFactory.reset(mediaServerItem.getId());
|
||||||
redisTemplate.opsForZSet().add(VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId(), mediaServerItem.getId(), 0);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,16 +204,8 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||||
mediaServerMapper.update(mediaSerItem);
|
mediaServerMapper.update(mediaSerItem);
|
||||||
MediaServerItem mediaServerItemInRedis = getOne(mediaSerItem.getId());
|
MediaServerItem mediaServerItemInRedis = getOne(mediaSerItem.getId());
|
||||||
MediaServerItem mediaServerItemInDataBase = mediaServerMapper.queryOne(mediaSerItem.getId());
|
MediaServerItem mediaServerItemInDataBase = mediaServerMapper.queryOne(mediaSerItem.getId());
|
||||||
if (mediaServerItemInRedis != null && mediaServerItemInRedis.getSsrcConfig() != null) {
|
if (mediaServerItemInRedis == null || ssrcFactory.hasMediaServerSSRC(mediaSerItem.getId())) {
|
||||||
mediaServerItemInDataBase.setSsrcConfig(mediaServerItemInRedis.getSsrcConfig());
|
ssrcFactory.initMediaServerSSRC(mediaServerItemInDataBase.getId(),null);
|
||||||
}else {
|
|
||||||
mediaServerItemInDataBase.setSsrcConfig(
|
|
||||||
new SsrcConfig(
|
|
||||||
mediaServerItemInDataBase.getId(),
|
|
||||||
null,
|
|
||||||
sipConfig.getDomain()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItemInDataBase.getId();
|
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItemInDataBase.getId();
|
||||||
redisTemplate.opsForValue().set(key, mediaServerItemInDataBase);
|
redisTemplate.opsForValue().set(key, mediaServerItemInDataBase);
|
||||||
|
@ -404,14 +386,8 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||||
}
|
}
|
||||||
mediaServerMapper.update(serverItem);
|
mediaServerMapper.update(serverItem);
|
||||||
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + zlmServerConfig.getGeneralMediaServerId();
|
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + zlmServerConfig.getGeneralMediaServerId();
|
||||||
if (redisTemplate.opsForValue().get(key) == null) {
|
if (ssrcFactory.hasMediaServerSSRC(serverItem.getId())) {
|
||||||
SsrcConfig ssrcConfig = new SsrcConfig(zlmServerConfig.getGeneralMediaServerId(), null, sipConfig.getDomain());
|
ssrcFactory.initMediaServerSSRC(zlmServerConfig.getGeneralMediaServerId(), null);
|
||||||
serverItem.setSsrcConfig(ssrcConfig);
|
|
||||||
}else {
|
|
||||||
MediaServerItem mediaServerItemInRedis = JsonUtil.redisJsonToObject(redisTemplate, key, MediaServerItem.class);
|
|
||||||
if (Objects.nonNull(mediaServerItemInRedis)) {
|
|
||||||
serverItem.setSsrcConfig(mediaServerItemInRedis.getSsrcConfig());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
redisTemplate.opsForValue().set(key, serverItem);
|
redisTemplate.opsForValue().set(key, serverItem);
|
||||||
resetOnlineServerItem(serverItem);
|
resetOnlineServerItem(serverItem);
|
||||||
|
@ -709,8 +685,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||||
}
|
}
|
||||||
// zlm连接重试
|
// zlm连接重试
|
||||||
logger.warn("[更新ZLM 保活信息]尝试链接zml id {}", mediaServerId);
|
logger.warn("[更新ZLM 保活信息]尝试链接zml id {}", mediaServerId);
|
||||||
SsrcConfig ssrcConfig = new SsrcConfig(mediaServerItem.getId(), null, sipConfig.getDomain());
|
ssrcFactory.initMediaServerSSRC(mediaServerItem.getId(), null);
|
||||||
mediaServerItem.setSsrcConfig(ssrcConfig);
|
|
||||||
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId();
|
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId();
|
||||||
redisTemplate.opsForValue().set(key, mediaServerItem);
|
redisTemplate.opsForValue().set(key, mediaServerItem);
|
||||||
clearRTPServer(mediaServerItem);
|
clearRTPServer(mediaServerItem);
|
||||||
|
|
|
@ -11,6 +11,7 @@ import com.genersoft.iot.vmp.conf.exception.ServiceException;
|
||||||
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
|
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
|
||||||
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||||
|
@ -100,6 +101,9 @@ public class PlayServiceImpl implements IPlayService {
|
||||||
@Autowired
|
@Autowired
|
||||||
private ZlmHttpHookSubscribe subscribe;
|
private ZlmHttpHookSubscribe subscribe;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SSRCFactory ssrcFactory;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedisTemplate<Object, Object> redisTemplate;
|
private RedisTemplate<Object, Object> redisTemplate;
|
||||||
|
|
||||||
|
@ -298,10 +302,10 @@ public class PlayServiceImpl implements IPlayService {
|
||||||
if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) {
|
if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) {
|
||||||
logger.info("[点播消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse);
|
logger.info("[点播消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse);
|
||||||
|
|
||||||
if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) {
|
if (!ssrcFactory.checkSsrc(mediaServerItem.getId(),ssrcInResponse)) {
|
||||||
// ssrc 不可用
|
// ssrc 不可用
|
||||||
// 释放ssrc
|
// 释放ssrc
|
||||||
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
|
ssrcFactory.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
|
||||||
streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
|
streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
|
||||||
event.msg = "下级自定义了ssrc,但是此ssrc不可用";
|
event.msg = "下级自定义了ssrc,但是此ssrc不可用";
|
||||||
event.statusCode = 400;
|
event.statusCode = 400;
|
||||||
|
@ -539,7 +543,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||||
if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) {
|
if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) {
|
||||||
logger.info("[回放消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse);
|
logger.info("[回放消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse);
|
||||||
|
|
||||||
if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) {
|
if (!ssrcFactory.checkSsrc(mediaServerItem.getId(),ssrcInResponse)) {
|
||||||
// ssrc 不可用
|
// ssrc 不可用
|
||||||
// 释放ssrc
|
// 释放ssrc
|
||||||
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
|
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
|
||||||
|
@ -678,7 +682,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||||
if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) {
|
if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) {
|
||||||
logger.info("[回放消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse);
|
logger.info("[回放消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse);
|
||||||
|
|
||||||
if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) {
|
if (!ssrcFactory.checkSsrc(mediaServerItem.getId(),ssrcInResponse)) {
|
||||||
// ssrc 不可用
|
// ssrc 不可用
|
||||||
// 释放ssrc
|
// 释放ssrc
|
||||||
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
|
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
package com.genersoft.iot.vmp.utils;
|
|
||||||
|
|
||||||
public class ConfigConst {
|
|
||||||
/**
|
|
||||||
* 播流最大并发个数
|
|
||||||
*/
|
|
||||||
public static final Integer MAX_STRTEAM_COUNT = 10000;
|
|
||||||
}
|
|
Loading…
Reference in New Issue