|
|
@@ -10,11 +10,12 @@ import com.genersoft.iot.vmp.gb28181.dao.DeviceMapper;
|
|
|
import com.genersoft.iot.vmp.gb28181.service.IInviteStreamService;
|
|
|
import com.genersoft.iot.vmp.media.event.media.MediaDepartureEvent;
|
|
|
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
|
|
-import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.context.event.EventListener;
|
|
|
+import org.springframework.data.redis.core.Cursor;
|
|
|
import org.springframework.data.redis.core.RedisTemplate;
|
|
|
+import org.springframework.data.redis.core.ScanOptions;
|
|
|
import org.springframework.scheduling.annotation.Async;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
@@ -23,7 +24,6 @@ import java.util.List;
|
|
|
import java.util.Map;
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
import java.util.concurrent.CopyOnWriteArrayList;
|
|
|
-import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
@Slf4j
|
|
|
@Service
|
|
|
@@ -61,11 +61,12 @@ public class InviteStreamServiceImpl implements IInviteStreamService {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
@Override
|
|
|
public void updateInviteInfo(InviteInfo inviteInfo) {
|
|
|
if (InviteSessionStatus.ready == inviteInfo.getStatus()) {
|
|
|
updateInviteInfo(inviteInfo, Long.valueOf(userSetting.getPlayTimeout()) * 2);
|
|
|
- }else {
|
|
|
+ } else {
|
|
|
updateInviteInfo(inviteInfo, null);
|
|
|
}
|
|
|
}
|
|
|
@@ -114,16 +115,15 @@ public class InviteStreamServiceImpl implements IInviteStreamService {
|
|
|
inviteInfoForUpdate = inviteInfoInRedis;
|
|
|
|
|
|
}
|
|
|
- String key = VideoManagerConstants.INVITE_PREFIX +
|
|
|
- ":" + inviteInfoForUpdate.getType() +
|
|
|
+ String key = VideoManagerConstants.INVITE_PREFIX;
|
|
|
+ String objectKey = inviteInfoForUpdate.getType() +
|
|
|
":" + inviteInfoForUpdate.getChannelId() +
|
|
|
- ":" + inviteInfoForUpdate.getStream()+
|
|
|
+ ":" + inviteInfoForUpdate.getStream() +
|
|
|
":" + inviteInfoForUpdate.getSsrcInfo().getSsrc();
|
|
|
if (time != null && time > 0) {
|
|
|
- redisTemplate.opsForValue().set(key, inviteInfoForUpdate, time, TimeUnit.SECONDS);
|
|
|
- }else {
|
|
|
- redisTemplate.opsForValue().set(key, inviteInfoForUpdate);
|
|
|
+ inviteInfoForUpdate.setExpirationTime(time);
|
|
|
}
|
|
|
+ redisTemplate.opsForHash().put(key, objectKey, inviteInfoForUpdate);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
@@ -134,8 +134,8 @@ public class InviteStreamServiceImpl implements IInviteStreamService {
|
|
|
return null;
|
|
|
}
|
|
|
removeInviteInfo(inviteInfoInDb);
|
|
|
- String key = VideoManagerConstants.INVITE_PREFIX +
|
|
|
- ":" + inviteInfo.getType() +
|
|
|
+ String key = VideoManagerConstants.INVITE_PREFIX;
|
|
|
+ String objectKey = inviteInfo.getType() +
|
|
|
":" + inviteInfo.getChannelId() +
|
|
|
":" + stream +
|
|
|
":" + inviteInfo.getSsrcInfo().getSsrc();
|
|
|
@@ -144,46 +144,43 @@ public class InviteStreamServiceImpl implements IInviteStreamService {
|
|
|
inviteInfoInDb.getSsrcInfo().setStream(stream);
|
|
|
}
|
|
|
if (InviteSessionStatus.ready == inviteInfo.getStatus()) {
|
|
|
- redisTemplate.opsForValue().set(key, inviteInfoInDb, userSetting.getPlayTimeout() * 2, TimeUnit.SECONDS);
|
|
|
- }else {
|
|
|
- redisTemplate.opsForValue().set(key, inviteInfoInDb);
|
|
|
+ inviteInfoInDb.setExpirationTime((long) (userSetting.getPlayTimeout() * 2));
|
|
|
}
|
|
|
-
|
|
|
+ redisTemplate.opsForHash().put(key, objectKey, inviteInfoInDb);
|
|
|
return inviteInfoInDb;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public InviteInfo getInviteInfo(InviteSessionType type, Integer channelId, String stream) {
|
|
|
- String key = VideoManagerConstants.INVITE_PREFIX +
|
|
|
- ":" + (type != null ? type : "*") +
|
|
|
+ String key = VideoManagerConstants.INVITE_PREFIX;
|
|
|
+ String keyPattern = (type != null ? type : "*") +
|
|
|
":" + (channelId != null ? channelId : "*") +
|
|
|
":" + (stream != null ? stream : "*")
|
|
|
+ ":*";
|
|
|
- List<Object> scanResult = RedisUtil.scan(redisTemplate, key);
|
|
|
- if (scanResult.isEmpty()) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- if (scanResult.size() != 1) {
|
|
|
- log.warn("[获取InviteInfo] 发现 key: {}存在多条", key);
|
|
|
- }
|
|
|
+ ScanOptions options = ScanOptions.scanOptions().match(keyPattern).count(20).build();
|
|
|
+ try (Cursor<Map.Entry<Object, Object>> cursor = redisTemplate.opsForHash().scan(key, options)) {
|
|
|
+ if (cursor.hasNext()) {
|
|
|
+ InviteInfo inviteInfo = (InviteInfo) cursor.next().getValue();
|
|
|
+ cursor.close();
|
|
|
+ return inviteInfo;
|
|
|
|
|
|
- return (InviteInfo) redisTemplate.opsForValue().get(scanResult.get(0));
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("[Redis-InviteInfo] 查询异常: ", e);
|
|
|
+ }
|
|
|
+ return null;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public List<InviteInfo> getAllInviteInfo(InviteSessionType type, Integer channelId, String stream) {
|
|
|
- String key = VideoManagerConstants.INVITE_PREFIX +
|
|
|
- ":" + (type != null ? type : "*") +
|
|
|
- ":" + (channelId != null ? channelId : "*") +
|
|
|
- ":" + (stream != null ? stream : "*")
|
|
|
- + ":*";
|
|
|
- List<Object> scanResult = RedisUtil.scan(redisTemplate, key);
|
|
|
- if (scanResult.isEmpty()) {
|
|
|
- return new ArrayList<>();
|
|
|
- }
|
|
|
+ public List<InviteInfo> getAllInviteInfo() {
|
|
|
List<InviteInfo> result = new ArrayList<>();
|
|
|
- for (Object keyObj : scanResult) {
|
|
|
- result.add((InviteInfo) redisTemplate.opsForValue().get(keyObj));
|
|
|
+ String key = VideoManagerConstants.INVITE_PREFIX;
|
|
|
+ List<Object> values = redisTemplate.opsForHash().values(key);
|
|
|
+ if(values.isEmpty()) {
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ for (Object value : values) {
|
|
|
+ result.add((InviteInfo)value);
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
@@ -199,23 +196,22 @@ public class InviteStreamServiceImpl implements IInviteStreamService {
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public void removeInviteInfo(InviteSessionType type, Integer channelId, String stream) {
|
|
|
- String scanKey = VideoManagerConstants.INVITE_PREFIX +
|
|
|
- ":" + (type != null ? type : "*") +
|
|
|
- ":" + (channelId != null ? channelId : "*") +
|
|
|
- ":" + (stream != null ? stream : "*") +
|
|
|
- ":*";
|
|
|
- List<Object> scanResult = RedisUtil.scan(redisTemplate, scanKey);
|
|
|
- if (!scanResult.isEmpty()) {
|
|
|
- for (Object keyObj : scanResult) {
|
|
|
- String key = (String) keyObj;
|
|
|
- InviteInfo inviteInfo = (InviteInfo) redisTemplate.opsForValue().get(key);
|
|
|
- if (inviteInfo == null) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- redisTemplate.delete(key);
|
|
|
- inviteErrorCallbackMap.remove(buildKey(type,channelId, inviteInfo.getStream()));
|
|
|
- }
|
|
|
+ public void removeInviteInfo(InviteSessionType type, Integer channelId, String stream) {
|
|
|
+ String key = VideoManagerConstants.INVITE_PREFIX;
|
|
|
+ if (type == null && channelId == null && stream == null) {
|
|
|
+ redisTemplate.opsForHash().delete(key);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ InviteInfo inviteInfo = getInviteInfo(type, channelId, stream);
|
|
|
+ if (inviteInfo != null) {
|
|
|
+ String objectKey = inviteInfo.getType() +
|
|
|
+ ":" + inviteInfo.getChannelId() +
|
|
|
+ ":" + stream +
|
|
|
+ ":" + inviteInfo.getSsrcInfo().getSsrc();
|
|
|
+ redisTemplate.opsForHash().delete(key, objectKey);
|
|
|
+ }
|
|
|
+ if (redisTemplate.opsForHash().size(key) == 0) {
|
|
|
+ redisTemplate.opsForHash().delete(key);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -230,14 +226,14 @@ public class InviteStreamServiceImpl implements IInviteStreamService {
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public void once(InviteSessionType type, Integer channelId, String stream, ErrorCallback<StreamInfo> callback) {
|
|
|
+ public void once(InviteSessionType type, Integer channelId, String stream, ErrorCallback<StreamInfo> callback) {
|
|
|
String key = buildKey(type, channelId, stream);
|
|
|
List<ErrorCallback<StreamInfo>> callbacks = inviteErrorCallbackMap.computeIfAbsent(key, k -> new CopyOnWriteArrayList<>());
|
|
|
callbacks.add(callback);
|
|
|
|
|
|
}
|
|
|
|
|
|
- private String buildKey(InviteSessionType type, Integer channelId, String stream) {
|
|
|
+ private String buildKey(InviteSessionType type, Integer channelId, String stream) {
|
|
|
String key = type + ":" + channelId;
|
|
|
// 如果ssrc未null那么可以实现一个通道只能一次操作,ssrc不为null则可以支持一个通道多次invite
|
|
|
if (stream != null) {
|
|
|
@@ -249,7 +245,7 @@ public class InviteStreamServiceImpl implements IInviteStreamService {
|
|
|
|
|
|
@Override
|
|
|
public void clearInviteInfo(String deviceId) {
|
|
|
- List<InviteInfo> inviteInfoList = getAllInviteInfo(null, null, null);
|
|
|
+ List<InviteInfo> inviteInfoList = getAllInviteInfo();
|
|
|
for (InviteInfo inviteInfo : inviteInfoList) {
|
|
|
if (inviteInfo.getDeviceId().equals(deviceId)) {
|
|
|
removeInviteInfo(inviteInfo);
|
|
|
@@ -260,23 +256,21 @@ public class InviteStreamServiceImpl implements IInviteStreamService {
|
|
|
@Override
|
|
|
public int getStreamInfoCount(String mediaServerId) {
|
|
|
int count = 0;
|
|
|
- String key = VideoManagerConstants.INVITE_PREFIX + ":*:*:*:*";
|
|
|
- List<Object> scanResult = RedisUtil.scan(redisTemplate, key);
|
|
|
- if (scanResult.isEmpty()) {
|
|
|
- return 0;
|
|
|
- }else {
|
|
|
- for (Object keyObj : scanResult) {
|
|
|
- String keyStr = (String) keyObj;
|
|
|
- InviteInfo inviteInfo = (InviteInfo) redisTemplate.opsForValue().get(keyStr);
|
|
|
- if (inviteInfo != null
|
|
|
- && inviteInfo.getStreamInfo() != null
|
|
|
- && inviteInfo.getStreamInfo().getMediaServer() != null
|
|
|
- && inviteInfo.getStreamInfo().getMediaServer().getId().equals(mediaServerId)) {
|
|
|
- if (inviteInfo.getType().equals(InviteSessionType.DOWNLOAD) && inviteInfo.getStreamInfo().getProgress() == 1) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- count++;
|
|
|
+ String key = VideoManagerConstants.INVITE_PREFIX;
|
|
|
+ List<Object> values = redisTemplate.opsForHash().values(key);
|
|
|
+ if (values.isEmpty()) {
|
|
|
+ return count;
|
|
|
+ }
|
|
|
+ for (Object value : values) {
|
|
|
+ InviteInfo inviteInfo = (InviteInfo)value;
|
|
|
+ if (inviteInfo != null
|
|
|
+ && inviteInfo.getStreamInfo() != null
|
|
|
+ && inviteInfo.getStreamInfo().getMediaServer() != null
|
|
|
+ && inviteInfo.getStreamInfo().getMediaServer().getId().equals(mediaServerId)) {
|
|
|
+ if (inviteInfo.getType().equals(InviteSessionType.DOWNLOAD) && inviteInfo.getStreamInfo().getProgress() == 1) {
|
|
|
+ continue;
|
|
|
}
|
|
|
+ count++;
|
|
|
}
|
|
|
}
|
|
|
return count;
|
|
|
@@ -309,13 +303,16 @@ public class InviteStreamServiceImpl implements IInviteStreamService {
|
|
|
|
|
|
@Override
|
|
|
public InviteInfo getInviteInfoBySSRC(String ssrc) {
|
|
|
- String key = VideoManagerConstants.INVITE_PREFIX + ":*:*:*:" + ssrc;
|
|
|
- List<Object> scanResult = RedisUtil.scan(redisTemplate, key);
|
|
|
- if (scanResult.size() != 1) {
|
|
|
+ List<InviteInfo> inviteInfoList = getAllInviteInfo();
|
|
|
+ if (inviteInfoList.isEmpty()) {
|
|
|
return null;
|
|
|
}
|
|
|
-
|
|
|
- return (InviteInfo) redisTemplate.opsForValue().get(scanResult.get(0));
|
|
|
+ for (InviteInfo inviteInfo : inviteInfoList) {
|
|
|
+ if (inviteInfo.getSsrcInfo() != null && ssrc.equals(inviteInfo.getSsrcInfo().getSsrc())) {
|
|
|
+ return inviteInfo;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
@@ -325,15 +322,15 @@ public class InviteStreamServiceImpl implements IInviteStreamService {
|
|
|
return null;
|
|
|
}
|
|
|
removeInviteInfo(inviteInfoInDb);
|
|
|
- String key = VideoManagerConstants.INVITE_PREFIX +
|
|
|
- ":" + inviteInfo.getType() +
|
|
|
+ String key = VideoManagerConstants.INVITE_PREFIX;
|
|
|
+ String objectKey = inviteInfo.getType() +
|
|
|
":" + inviteInfo.getChannelId() +
|
|
|
":" + inviteInfo.getStream() +
|
|
|
":" + ssrc;
|
|
|
if (inviteInfoInDb.getSsrcInfo() != null) {
|
|
|
inviteInfoInDb.getSsrcInfo().setSsrc(ssrc);
|
|
|
}
|
|
|
- redisTemplate.opsForValue().set(key, inviteInfoInDb);
|
|
|
+ redisTemplate.opsForHash().put(key, objectKey, inviteInfoInDb);
|
|
|
return inviteInfoInDb;
|
|
|
}
|
|
|
}
|