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.java
This commit is contained in:
@@ -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.gb28181.bean.*;
|
||||
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.transmit.SIPProcessorObserver;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.SIPSender;
|
||||
@@ -74,6 +74,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
@Autowired
|
||||
private IRedisCatchStorage redisCatchStorage;
|
||||
|
||||
@Autowired
|
||||
private SSRCFactory ssrcFactory;
|
||||
|
||||
@Autowired
|
||||
private DynamicTask dynamicTask;
|
||||
|
||||
@@ -491,12 +494,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
} else if (gbStream != null) {
|
||||
if(ssrc.equals(ssrcDefault))
|
||||
{
|
||||
SsrcConfig ssrcConfig = mediaServerItem.getSsrcConfig();
|
||||
if(ssrcConfig != null)
|
||||
{
|
||||
ssrc = ssrcConfig.getPlaySsrc();
|
||||
ssrcConfig.releaseSsrc(ssrc);
|
||||
}
|
||||
ssrc = ssrcFactory.getPlaySsrc(mediaServerItem.getId());
|
||||
ssrcFactory.releaseSsrc(mediaServerItem.getId(), ssrc);
|
||||
}
|
||||
if("push".equals(gbStream.getStreamType())) {
|
||||
if (streamPushItem != null && streamPushItem.isPushIng()) {
|
||||
|
||||
Reference in New Issue
Block a user