优化集群方案, 每个zlm一套ssrc;
优化集群下的docker接入逻辑; 更正sql脚本; 支持重启不设置设备离线。重启SIP事务不丢失
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
package com.genersoft.iot.vmp.gb28181.session;
|
||||
|
||||
import com.genersoft.iot.vmp.utils.ConfigConst;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
public class SsrcConfig {
|
||||
|
||||
/**
|
||||
* zlm流媒体服务器Id
|
||||
*/
|
||||
private String mediaServerId;
|
||||
|
||||
private String ssrcPrefix;
|
||||
/**
|
||||
* zlm流媒体服务器已用会话句柄
|
||||
*/
|
||||
private List<String> isUsed;
|
||||
/**
|
||||
* 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){
|
||||
System.out.printf("11111");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取后四位数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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
package com.genersoft.iot.vmp.gb28181.session;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.SipConfig;
|
||||
import com.genersoft.iot.vmp.utils.SpringBeanFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* @Description:SIP信令中的SSRC工具类。SSRC值由10位十进制整数组成的字符串,第一位为0代表实况,为1则代表回放;第二位至第六位由监控域ID的第4位到第8位组成;最后4位为不重复的4个整数
|
||||
* @author: swwheihei
|
||||
* @date: 2020年5月10日 上午11:57:57
|
||||
*/
|
||||
public class SsrcUtil {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(SsrcUtil.class);
|
||||
|
||||
private static String ssrcPrefix;
|
||||
|
||||
private static List<String> isUsed;
|
||||
|
||||
private static List<String> notUsed;
|
||||
|
||||
private static void init() {
|
||||
SipConfig sipConfig = (SipConfig) SpringBeanFactory.getBean("sipConfig");
|
||||
ssrcPrefix = sipConfig.getSipDomain().substring(3, 8);
|
||||
isUsed = new ArrayList<String>();
|
||||
notUsed = new ArrayList<String>();
|
||||
for (int i = 1; i < 10000; i++) {
|
||||
if (i < 10) {
|
||||
notUsed.add("000" + i);
|
||||
} else if (i < 100) {
|
||||
notUsed.add("00" + i);
|
||||
} else if (i < 1000) {
|
||||
notUsed.add("0" + i);
|
||||
} else {
|
||||
notUsed.add(String.valueOf(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取视频预览的SSRC值,第一位固定为0
|
||||
*
|
||||
*/
|
||||
public static String getPlaySsrc() {
|
||||
return "0" + getSsrcPrefix() + getSN();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取录像回放的SSRC值,第一位固定为1
|
||||
*
|
||||
*/
|
||||
public static String getPlayBackSsrc() {
|
||||
return "1" + getSsrcPrefix() + getSN();
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放ssrc,主要用完的ssrc一定要释放,否则会耗尽
|
||||
*
|
||||
*/
|
||||
public static void releaseSsrc(String ssrc) {
|
||||
if (ssrc == null) {
|
||||
logger.error("要释放ssrc为null");
|
||||
return;
|
||||
}
|
||||
String sn = ssrc.substring(6);
|
||||
isUsed.remove(sn);
|
||||
notUsed.add(sn);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取后四位数SN,随机数
|
||||
*
|
||||
*/
|
||||
private static 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;
|
||||
}
|
||||
|
||||
private static String getSsrcPrefix() {
|
||||
if (ssrcPrefix == null) {
|
||||
init();
|
||||
}
|
||||
return ssrcPrefix;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,23 @@
|
||||
package com.genersoft.iot.vmp.gb28181.session;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.sip.ClientTransaction;
|
||||
import javax.sip.Dialog;
|
||||
import javax.sip.message.Request;
|
||||
|
||||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
|
||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.utils.SerializeUtils;
|
||||
import com.genersoft.iot.vmp.utils.redis.JedisUtil;
|
||||
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
||||
import gov.nist.javax.sip.stack.SIPDialog;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
@@ -14,50 +28,85 @@ import org.springframework.stereotype.Component;
|
||||
@Component
|
||||
public class VideoStreamSessionManager {
|
||||
|
||||
private ConcurrentHashMap<String, ClientTransaction> sessionMap = new ConcurrentHashMap<>();
|
||||
private ConcurrentHashMap<String, String> ssrcMap = new ConcurrentHashMap<>();
|
||||
private ConcurrentHashMap<String, String> streamIdMap = new ConcurrentHashMap<>();
|
||||
@Autowired
|
||||
private RedisUtil redisUtil;
|
||||
|
||||
public String createPlaySsrc(){
|
||||
return SsrcUtil.getPlaySsrc();
|
||||
public void put(String deviceId, String channelId ,String ssrc, String streamId, String mediaServerId, ClientTransaction transaction){
|
||||
SsrcTransaction ssrcTransaction = new SsrcTransaction();
|
||||
ssrcTransaction.setDeviceId(deviceId);
|
||||
ssrcTransaction.setChannelId(channelId);
|
||||
ssrcTransaction.setStreamId(streamId);
|
||||
byte[] transactionByteArray = SerializeUtils.serialize(transaction);
|
||||
ssrcTransaction.setTransaction(transactionByteArray);
|
||||
ssrcTransaction.setSsrc(ssrc);
|
||||
ssrcTransaction.setMediaServerId(mediaServerId);
|
||||
|
||||
redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + deviceId + "_" + channelId, ssrcTransaction);
|
||||
}
|
||||
|
||||
public String createPlayBackSsrc(){
|
||||
return SsrcUtil.getPlayBackSsrc();
|
||||
}
|
||||
|
||||
public void put(String deviceId, String channelId ,String ssrc, String streamId, ClientTransaction transaction){
|
||||
sessionMap.put(deviceId + "_" + channelId, transaction);
|
||||
ssrcMap.put(deviceId + "_" + channelId, ssrc);
|
||||
streamIdMap.put(deviceId + "_" + channelId, streamId);
|
||||
|
||||
public void put(String deviceId, String channelId , Dialog dialog){
|
||||
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
|
||||
if (ssrcTransaction != null) {
|
||||
byte[] dialogByteArray = SerializeUtils.serialize(dialog);
|
||||
ssrcTransaction.setDialog(dialogByteArray);
|
||||
}
|
||||
redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + deviceId + "_" + channelId, ssrcTransaction);
|
||||
}
|
||||
|
||||
|
||||
public ClientTransaction getTransaction(String deviceId, String channelId){
|
||||
return sessionMap.get(deviceId + "_" + channelId);
|
||||
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
|
||||
if (ssrcTransaction == null) return null;
|
||||
byte[] transactionByteArray = ssrcTransaction.getTransaction();
|
||||
ClientTransaction clientTransaction = (ClientTransaction)SerializeUtils.deSerialize(transactionByteArray);
|
||||
return clientTransaction;
|
||||
}
|
||||
|
||||
public SIPDialog getDialog(String deviceId, String channelId){
|
||||
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
|
||||
if (ssrcTransaction == null) return null;
|
||||
byte[] dialogByteArray = ssrcTransaction.getDialog();
|
||||
if (dialogByteArray == null) return null;
|
||||
SIPDialog dialog = (SIPDialog)SerializeUtils.deSerialize(dialogByteArray);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public SsrcTransaction getSsrcTransaction(String deviceId, String channelId){
|
||||
SsrcTransaction ssrcTransaction = (SsrcTransaction)redisUtil.get(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + deviceId + "_" + channelId);
|
||||
return ssrcTransaction;
|
||||
}
|
||||
|
||||
public String getStreamId(String deviceId, String channelId){
|
||||
return streamIdMap.get(deviceId + "_" + channelId);
|
||||
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
|
||||
if (ssrcTransaction == null) return null;
|
||||
return ssrcTransaction.getStreamId();
|
||||
}
|
||||
public String getMediaServerId(String deviceId, String channelId){
|
||||
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
|
||||
if (ssrcTransaction == null) return null;
|
||||
return ssrcTransaction.getMediaServerId();
|
||||
}
|
||||
|
||||
public String getSSRC(String deviceId, String channelId){
|
||||
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
|
||||
if (ssrcTransaction == null) return null;
|
||||
return ssrcTransaction.getSsrc();
|
||||
}
|
||||
|
||||
public void remove(String deviceId, String channelId) {
|
||||
sessionMap.remove(deviceId + "_" + channelId);
|
||||
if (ssrcMap.get(deviceId + "_" + channelId) != null) {
|
||||
SsrcUtil.releaseSsrc(ssrcMap.get(deviceId + "_" + channelId));
|
||||
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
|
||||
if (ssrcTransaction == null) return;
|
||||
redisUtil.del(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + deviceId + "_" + channelId);
|
||||
}
|
||||
|
||||
public List<SsrcTransaction> getAllSsrc() {
|
||||
List<Object> ssrcTransactionKeys = redisUtil.scan(String.format("%s_*_*", VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX));
|
||||
List<SsrcTransaction> result= new ArrayList<>();
|
||||
for (int i = 0; i < ssrcTransactionKeys.size(); i++) {
|
||||
String key = (String)ssrcTransactionKeys.get(i);
|
||||
SsrcTransaction ssrcTransaction = (SsrcTransaction)redisUtil.get(key);
|
||||
result.add(ssrcTransaction);
|
||||
}
|
||||
ssrcMap.remove(deviceId + "_" + channelId);
|
||||
streamIdMap.remove(deviceId + "_" + channelId);
|
||||
}
|
||||
|
||||
public ConcurrentHashMap<String, ClientTransaction> getSessionMap() {
|
||||
return sessionMap;
|
||||
}
|
||||
|
||||
public ConcurrentHashMap<String, String> getSsrcMap() {
|
||||
return ssrcMap;
|
||||
}
|
||||
|
||||
public ConcurrentHashMap<String, String> getStreamIdMap() {
|
||||
return streamIdMap;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user