Compare commits

...

8 Commits

Author SHA1 Message Date
阿斌
c8f425f137
Pre Merge pull request !36 from 阿斌/N/A 2026-04-13 03:44:51 +00:00
lin
a9f2e406ce 修复dockerFile jdk版本 #2116 2026-04-13 11:44:25 +08:00
lin
c35bb73091 修复合并PR时的数据导入问题 2026-04-13 11:05:45 +08:00
648540858
2e149dc2a2
Merge pull request #2110 from q792602257/fix/ssrc_recycle
修复ssrc回收逻辑
2026-04-13 10:58:24 +08:00
648540858
f38f0bebdd
Merge pull request #2078 from yanyu510/docker_env
fix: docker环境下sip信令IP问题
2026-04-13 10:24:59 +08:00
Jerry Yan
6273c89b9d 修复SSRC无法正确回收的逻辑 2026-04-07 17:19:11 +08:00
yy
6741adb55b fix: docker环境下sip信令IP问题 2026-01-30 21:40:19 +08:00
阿斌
da98101aac
update src/main/resources/civilCode.csv.
行政规划错误。江苏南通海门市,修改为海门区,浙江杭州删除下城区、江干区,新增钱塘区,临平区

Signed-off-by: 阿斌 <38912748@qq.com>
2024-12-15 08:58:42 +00:00
23 changed files with 286 additions and 110 deletions

View File

@ -101,6 +101,8 @@ services:
- ./logs/wvp:/opt/wvp/logs/
environment:
TZ: "Asia/Shanghai"
# docker env
RUN_ENV: "docker"
# 流链接的IP
Stream_IP: ${Stream_IP}
# SDP里的IP

View File

@ -1,4 +1,4 @@
FROM ringcentral/jdk:11 AS builder
FROM ringcentral/jdk:21.0.9 AS builder
EXPOSE 18978/tcp
EXPOSE 8116/tcp
@ -41,8 +41,8 @@ EXPOSE 8080/tcp
#ENV JAVA_HOME /usr/local/java/
#ENV JRE_HOME ${JAVA_HOME}/jre
#ENV CLASSPATH .:${JAVA_HOME}/lib:${JRE_HOME}/lib
#ENV PATH ${JAVA_HOME}/bin:$PATH
#ENV CLASSPATH .:${JAVA_HOME}/lib:${JRE_HOME}/lib
#ENV PATH ${JAVA_HOME}/bin:$PATH
RUN java -version && javac -version
@ -50,17 +50,17 @@ RUN java -version && javac -version
RUN apt-get update && \
apt-get install -y maven && \
rm -rf /var/lib/apt/lists/*
COPY . /build
WORKDIR /build
RUN ls && mvn clean package -Dmaven.test.skip=true
WORKDIR /build/target
#确保文件名一致
#ȷ<EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>
RUN mv wvp-pro-*.jar wvp.jar
FROM ringcentral/jdk:11
FROM ringcentral/jdk:21.0.9
RUN mkdir -p /opt/wvp
WORKDIR /opt/wvp
COPY --from=builder /build/target /opt/wvp
@ -82,4 +82,4 @@ ENTRYPOINT ["java", "-Xms512m", "-Xmx1024m", "-XX:+HeapDumpOnOutOfMemoryError",
#cp /home/wvp-GB28181-pro/target/*.jar /opt/wvp/wvp.jar
#
#WORKDIR /opt/wvp
#ENTRYPOINT ["java", "-Xms512m", "-Xmx1024m", "-XX:+HeapDumpOnOutOfMemoryError", "-XX:HeapDumpPath=/opt/ylcx/", "-jar", "wvp.jar", "--spring.config.location=/opt/ylcx/wvp/application.yml"]
#ENTRYPOINT ["java", "-Xms512m", "-Xmx1024m", "-XX:+HeapDumpOnOutOfMemoryError", "-XX:HeapDumpPath=/opt/ylcx/", "-jar", "wvp.jar", "--spring.config.location=/opt/ylcx/wvp/application.yml"]

View File

@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.GbStringMsgParserFactory;
import com.genersoft.iot.vmp.gb28181.conf.DefaultProperties;
import com.genersoft.iot.vmp.gb28181.transmit.ISIPProcessorObserver;
import com.genersoft.iot.vmp.utils.EnvUtil;
import gov.nist.javax.sip.SipProviderImpl;
import gov.nist.javax.sip.SipStackImpl;
import lombok.extern.slf4j.Slf4j;
@ -174,6 +175,9 @@ public class SipLayer implements CommandLineRunner {
}
public String getLocalIp(String deviceLocalIp) {
if(EnvUtil.isDockerEnv()){
return sipConfig.getShowIp();
}
if (monitorIps.size() == 1) {
return monitorIps.get(0);
}

View File

@ -10,6 +10,8 @@ public class InviteMessageInfo {
private String sourceChannelId;
private String sessionName;
private String ssrc;
private String allocatedSsrc;
private String allocatedSsrcMediaServerId;
private boolean tcp;
private boolean tcpActive;
private String callId;

View File

@ -24,6 +24,11 @@ public class SendRtpInfo {
*/
private String ssrc;
/**
* 从SSRC池中分配的SSRC
*/
private String allocatedSsrc;
/**
* 目标平台或设备的编号
*/
@ -247,4 +252,8 @@ public class SendRtpInfo {
this.setPlayType("Play".equalsIgnoreCase(sessionName) ? InviteStreamType.PLAY : InviteStreamType.PLAYBACK);
}
}
public String getSsrcToRelease() {
return allocatedSsrc;
}
}

View File

@ -47,6 +47,11 @@ public class SsrcTransaction {
*/
private String ssrc;
/**
* 从SSRC池中分配的SSRC
*/
private String allocatedSsrc;
/**
* 事务信息
*/
@ -88,4 +93,8 @@ public class SsrcTransaction {
public SsrcTransaction() {
}
public String getSsrcToRelease() {
return allocatedSsrc;
}
}

View File

@ -268,7 +268,7 @@ public class DeviceServiceImpl implements IDeviceService, CommandLineRunner {
List<SsrcTransaction> ssrcTransactions = sessionManager.getSsrcTransactionByDeviceId(device.getDeviceId());
if (ssrcTransactions != null && !ssrcTransactions.isEmpty()) {
for (SsrcTransaction ssrcTransaction : ssrcTransactions) {
mediaServerService.releaseSsrc(ssrcTransaction.getMediaServerId(), ssrcTransaction.getSsrc());
mediaServerService.releaseSsrc(ssrcTransaction.getMediaServerId(), ssrcTransaction.getSsrcToRelease());
receiveRtpServerService.closeRTPServerByMediaServerId(ssrcTransaction.getMediaServerId(), ssrcTransaction.getApp(), ssrcTransaction.getStream());
sessionManager.removeByCallId(ssrcTransaction.getCallId());
}

View File

@ -132,7 +132,7 @@ public class PlatformServiceImpl implements IPlatformService, CommandLineRunner
}
sendRtpServerService.delete(sendRtpItem);
if (mediaServerItem != null) {
ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrc());
ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrcToRelease());
boolean stopResult = mediaServerService.initStopSendRtp(mediaServerItem, sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getSsrc());
if (stopResult) {
Platform platform = queryPlatformByServerGBId(sendRtpItem.getTargetId());
@ -339,7 +339,7 @@ public class PlatformServiceImpl implements IPlatformService, CommandLineRunner
if (sendRtpItem != null && sendRtpItem.getApp().equals(event.getApp()) && sendRtpItem.isSendToPlatform()) {
Platform platform = platformMapper.getParentPlatByServerGBId(sendRtpItem.getTargetId());
CommonGBChannel channel = channelService.getOne(sendRtpItem.getChannelId());
ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrc());
ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrcToRelease());
try {
commanderForPlatform.streamByeCmd(platform, sendRtpItem, channel);
} catch (SipException | InvalidArgumentException | ParseException e) {
@ -526,7 +526,7 @@ public class PlatformServiceImpl implements IPlatformService, CommandLineRunner
List<SendRtpInfo> sendRtpItems = sendRtpServerService.queryForPlatform(platformId);
if (sendRtpItems != null && !sendRtpItems.isEmpty()) {
for (SendRtpInfo sendRtpItem : sendRtpItems) {
ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrc());
ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrcToRelease());
sendRtpServerService.delete(sendRtpItem);
MediaServer mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
mediaServerService.stopSendRtp(mediaInfo, sendRtpItem.getApp(), sendRtpItem.getStream(), null);
@ -647,7 +647,7 @@ public class PlatformServiceImpl implements IPlatformService, CommandLineRunner
log.error("[点播超时] 发送BYE失败 {}", e.getMessage());
} finally {
timeoutCallback.run(1, "收流超时");
mediaServerService.releaseSsrc(mediaServerItem.getId(), data.getSsrcInfo().getSsrc());
mediaServerService.releaseSsrc(mediaServerItem.getId(), data.getSsrcInfo().getSsrcToRelease());
receiveRtpServerService.closeRTPServer(mediaServerItem, data.getSsrcInfo().getApp(), data.getSsrcInfo().getStream());
sessionManager.removeByStream(data.getSsrcInfo().getApp(), data.getSsrcInfo().getStream());
}
@ -728,8 +728,7 @@ public class PlatformServiceImpl implements IPlatformService, CommandLineRunner
// ssrc检验
// 更新ssrc
log.info("[Invite 200OK] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse);
// 释放ssrc
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
releaseAllocatedSsrc(mediaServerItem, ssrcInfo);
Boolean result = mediaServerService.updateRtpServerSSRC(mediaServerItem, ssrcInfo.getApp(), ssrcInfo.getStream(), ssrcInResponse);
if (!result) {
try {
@ -739,7 +738,7 @@ public class PlatformServiceImpl implements IPlatformService, CommandLineRunner
log.error("[命令发送失败] 停止播放, 发送BYE: {}", e.getMessage());
} finally {
// 释放ssrc
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrcToRelease());
receiveRtpServerService.closeRTPServer(mediaServerItem, ssrcInfo.getApp(), ssrcInfo.getStream());
sessionManager.removeByStream(ssrcInfo.getApp(), ssrcInfo.getStream());
@ -751,6 +750,7 @@ public class PlatformServiceImpl implements IPlatformService, CommandLineRunner
}
}else {
ssrcInfo.setSsrc(ssrcInResponse);
updateSsrcTransaction(ssrcInfo.getApp(), ssrcInfo.getStream(), ssrcInResponse, null);
inviteInfo.setSsrcInfo(ssrcInfo);
inviteInfo.setStream(ssrcInfo.getStream());
if (tcpMode == 2) {
@ -764,7 +764,9 @@ public class PlatformServiceImpl implements IPlatformService, CommandLineRunner
inviteStreamService.updateInviteInfo(inviteInfo);
}
}else {
releaseAllocatedSsrc(mediaServerItem, ssrcInfo);
ssrcInfo.setSsrc(ssrcInResponse);
updateSsrcTransaction(ssrcInfo.getApp(), ssrcInfo.getStream(), ssrcInResponse, null);
inviteInfo.setSsrcInfo(ssrcInfo);
inviteInfo.setStream(ssrcInfo.getStream());
if (tcpMode == 2) {
@ -782,6 +784,10 @@ public class PlatformServiceImpl implements IPlatformService, CommandLineRunner
// 单端口
// 重新订阅流上线
SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransactionByStream(ssrcInfo.getApp(), inviteInfo.getStream());
if (ssrcTransaction == null) {
return;
}
releaseAllocatedSsrc(mediaServerItem, ssrcInfo);
sessionManager.removeByStream(ssrcInfo.getApp(), inviteInfo.getStream());
inviteStreamService.updateInviteInfoForSSRC(inviteInfo, ssrcInResponse);
@ -790,6 +796,7 @@ public class PlatformServiceImpl implements IPlatformService, CommandLineRunner
ssrcTransaction.setApp(ssrcInfo.getApp());
ssrcTransaction.setStream(inviteInfo.getStream());
ssrcTransaction.setSsrc(ssrcInResponse);
ssrcTransaction.setAllocatedSsrc(null);
ssrcTransaction.setMediaServerId(mediaServerItem.getId());
ssrcTransaction.setSipTransactionInfo(new SipTransactionInfo((SIPResponse) responseEvent.getResponse()));
ssrcTransaction.setType(inviteSessionType);
@ -800,6 +807,24 @@ public class PlatformServiceImpl implements IPlatformService, CommandLineRunner
}
}
private void releaseAllocatedSsrc(MediaServer mediaServerItem, SSRCInfo ssrcInfo) {
if (ssrcInfo == null || ssrcInfo.getAllocatedSsrc() == null) {
return;
}
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getAllocatedSsrc());
ssrcInfo.setAllocatedSsrc(null);
}
private void updateSsrcTransaction(String app, String stream, String ssrc, String allocatedSsrc) {
SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransactionByStream(app, stream);
if (ssrcTransaction == null) {
return;
}
ssrcTransaction.setSsrc(ssrc);
ssrcTransaction.setAllocatedSsrc(allocatedSsrc);
sessionManager.put(ssrcTransaction);
}
private void tcpActiveHandler(Platform platform, CommonGBChannel channel, String contentString,
MediaServer mediaServerItem, int tcpMode, boolean ssrcCheck,
@ -836,7 +861,7 @@ public class PlatformServiceImpl implements IPlatformService, CommandLineRunner
log.error("[TCP主动连接对方] serverGbId: {}, channelId: {}, 解析200OK的SDP信息失败", platform.getServerGBId(), channel.getGbDeviceId(), e);
receiveRtpServerService.closeRTPServer(mediaServerItem, ssrcInfo.getApp(), ssrcInfo.getStream());
// 释放ssrc
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrcToRelease());
sessionManager.removeByStream(ssrcInfo.getApp(), ssrcInfo.getStream());
callback.run(InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(),
@ -861,7 +886,7 @@ public class PlatformServiceImpl implements IPlatformService, CommandLineRunner
InviteInfo inviteInfo = inviteStreamService.getInviteInfo(null, channel.getGbId(), stream);
if (inviteInfo != null) {
// 释放ssrc
mediaServerService.releaseSsrc(mediaServerItem.getId(), inviteInfo.getSsrcInfo().getSsrc());
mediaServerService.releaseSsrc(mediaServerItem.getId(), inviteInfo.getSsrcInfo().getSsrcToRelease());
inviteStreamService.removeInviteInfo(inviteInfo);
}
sessionManager.removeByStream(app, stream);

View File

@ -495,8 +495,15 @@ public class PlayServiceImpl implements IPlayService {
try {
sendRtpInfo = sendRtpServerService.createSendRtpInfo(mediaServerItem, null, null, playSsrc, device.getDeviceId(), MediaApp.GB28181_TALK, stream,
channel.getId(), true, false);
if (sendRtpInfo == null) {
ssrcFactory.releaseSsrc(mediaServerItem.getId(), playSsrc);
audioEvent.call("获取发流端口失败");
return;
}
sendRtpInfo.setAllocatedSsrc(playSsrc);
sendRtpInfo.setPlayType(InviteStreamType.TALK);
}catch (PlayException e) {
ssrcFactory.releaseSsrc(mediaServerItem.getId(), playSsrc);
log.info("[语音对讲]开始 获取发流端口失败 deviceId: {}, channelId: {},", device.getDeviceId(), channel.getDeviceId());
return;
}
@ -523,7 +530,7 @@ public class PlayServiceImpl implements IPlayService {
log.error("[语音对讲]超时, 发送BYE失败 {}", e.getMessage());
} finally {
timeoutCallback.run();
mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpInfo.getSsrc());
mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpInfo.getSsrcToRelease());
sessionManager.removeByStream(sendRtpInfo.getApp(), sendRtpInfo.getStream());
}
}, userSetting.getPlayTimeout());
@ -532,13 +539,13 @@ public class PlayServiceImpl implements IPlayService {
Integer localPort = mediaServerService.startSendRtpPassive(mediaServerItem, sendRtpInfo, userSetting.getPlayTimeout() * 1000);
if (localPort == null || localPort <= 0) {
timeoutCallback.run();
mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpInfo.getSsrc());
mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpInfo.getSsrcToRelease());
sessionManager.removeByStream(sendRtpInfo.getApp(), sendRtpInfo.getStream());
return;
}
sendRtpInfo.setPort(localPort);
}catch (ControllerException e) {
mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpInfo.getSsrc());
mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpInfo.getSsrcToRelease());
log.info("[语音对讲]失败 deviceId: {}, channelId: {}", device.getDeviceId(), channel.getDeviceId());
audioEvent.call("失败, " + e.getMessage());
// 查看是否已经建立了通道存在则发送bye
@ -584,7 +591,7 @@ public class PlayServiceImpl implements IPlayService {
dynamicTask.stop(timeOutTaskKey);
receiveRtpServerService.closeRTPServer(mediaServerItem, sendRtpInfo.getApp(), sendRtpInfo.getStream());
// 释放ssrc
mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpInfo.getSsrc());
mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpInfo.getSsrcToRelease());
sessionManager.removeByStream(sendRtpInfo.getApp(), sendRtpInfo.getStream());
errorEvent.response(event);
}, userSetting.getPlayTimeout().longValue());
@ -594,7 +601,7 @@ public class PlayServiceImpl implements IPlayService {
dynamicTask.stop(timeOutTaskKey);
receiveRtpServerService.closeRTPServer(mediaServerItem, sendRtpInfo.getApp(), sendRtpInfo.getStream());
// 释放ssrc
mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpInfo.getSsrc());
mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpInfo.getSsrcToRelease());
sessionManager.removeByStream(sendRtpInfo.getApp(), sendRtpInfo.getStream());
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult();
@ -879,8 +886,7 @@ public class PlayServiceImpl implements IPlayService {
// ssrc检验
// 更新ssrc
log.info("[Invite 200OK] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse);
// 释放ssrc
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
releaseAllocatedSsrc(mediaServerItem, ssrcInfo);
Boolean result = mediaServerService.updateRtpServerSSRC(mediaServerItem, ssrcInfo.getApp(), ssrcInfo.getStream(), ssrcInResponse);
if (!result) {
try {
@ -890,8 +896,7 @@ public class PlayServiceImpl implements IPlayService {
log.error("[命令发送失败] 停止播放, 发送BYE: {}", e.getMessage());
}
// 释放ssrc
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrcToRelease());
sessionManager.removeByStream(ssrcInfo.getApp(), ssrcInfo.getStream());
@ -903,6 +908,7 @@ public class PlayServiceImpl implements IPlayService {
}else {
ssrcInfo.setSsrc(ssrcInResponse);
updateSsrcTransaction(ssrcInfo.getApp(), ssrcInfo.getStream(), ssrcInResponse, null);
inviteInfo.setSsrcInfo(ssrcInfo);
inviteInfo.setStream(ssrcInfo.getStream());
if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE")) {
@ -914,18 +920,37 @@ public class PlayServiceImpl implements IPlayService {
}
inviteStreamService.updateInviteInfo(inviteInfo);
}
} else {
releaseAllocatedSsrc(mediaServerItem, ssrcInfo);
ssrcInfo.setSsrc(ssrcInResponse);
updateSsrcTransaction(ssrcInfo.getApp(), ssrcInfo.getStream(), ssrcInResponse, null);
inviteInfo.setSsrcInfo(ssrcInfo);
inviteInfo.setStream(ssrcInfo.getStream());
if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE")) {
if (mediaServerItem.isRtpEnable()) {
tcpActiveHandler(device, channel, contentString, mediaServerItem, ssrcInfo, callback);
}else {
log.warn("[Invite 200OK] 单端口收流模式不支持tcp主动模式收流");
}
}
inviteStreamService.updateInviteInfo(inviteInfo);
}
}else {
if (ssrcInResponse != null) {
// 单端口
// 重新订阅流上线
SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransactionByStream(MediaApp.GB28181, inviteInfo.getStream());
if (ssrcTransaction == null) {
return;
}
releaseAllocatedSsrc(mediaServerItem, ssrcInfo);
sessionManager.removeByStream(MediaApp.GB28181, inviteInfo.getStream());
inviteStreamService.updateInviteInfoForSSRC(inviteInfo, ssrcInResponse);
ssrcTransaction.setDeviceId(device.getDeviceId());
ssrcTransaction.setChannelId(ssrcTransaction.getChannelId());
ssrcTransaction.setCallId(ssrcTransaction.getCallId());
ssrcTransaction.setSsrc(ssrcInResponse);
ssrcTransaction.setAllocatedSsrc(null);
ssrcTransaction.setApp(MediaApp.GB28181);
ssrcTransaction.setStream(inviteInfo.getStream());
ssrcTransaction.setMediaServerId(mediaServerItem.getId());
@ -938,6 +963,24 @@ public class PlayServiceImpl implements IPlayService {
}
}
private void releaseAllocatedSsrc(MediaServer mediaServerItem, SSRCInfo ssrcInfo) {
if (ssrcInfo == null || ssrcInfo.getAllocatedSsrc() == null) {
return;
}
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getAllocatedSsrc());
ssrcInfo.setAllocatedSsrc(null);
}
private void updateSsrcTransaction(String app, String stream, String ssrc, String allocatedSsrc) {
SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransactionByStream(app, stream);
if (ssrcTransaction == null) {
return;
}
ssrcTransaction.setSsrc(ssrc);
ssrcTransaction.setAllocatedSsrc(allocatedSsrc);
sessionManager.put(ssrcTransaction);
}
@Override
public void download(Device device, DeviceChannel channel, String startTime, String endTime, int downloadSpeed, ErrorCallback<StreamInfo> callback) {
@ -1577,7 +1620,7 @@ public class PlayServiceImpl implements IPlayService {
mediaServerService.stopSendRtp(mediaServer, sendRtpInfo.getApp(), sendRtpInfo.getStream(), sendRtpInfo.getSsrc());
}
ssrcFactory.releaseSsrc(mediaServerId, sendRtpInfo.getSsrc());
ssrcFactory.releaseSsrc(mediaServerId, sendRtpInfo.getSsrcToRelease());
SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransactionByStream(sendRtpInfo.getApp(), sendRtpInfo.getStream());
if (ssrcTransaction != null) {

View File

@ -39,8 +39,7 @@ public class SSRCFactory {
public void initMediaServerSSRC(String mediaServerId, Set<String> usedSet) {
String sipDomain = sipConfig.getDomain();
String ssrcPrefix = sipDomain.length() >= 8 ? sipDomain.substring(3, 8) : sipDomain;
String ssrcPrefix = getSsrcPrefix();
String redisKey = SSRC_INFO_KEY + userSetting.getServerId() + "_" + mediaServerId;
List<String> ssrcList = new ArrayList<>();
for (int i = 1; i < MAX_STREAM_COUNT; i++) {
@ -83,7 +82,12 @@ public class SSRCFactory {
if (ssrc == null) {
return;
}
if (!isFactorySsrc(ssrc)) {
log.warn("[释放 SSRC] 忽略非SSRC池分配的值: {}", ssrc);
return;
}
String sn = ssrc.substring(1);
log.debug("[释放 SSRC] SSRC:{} -> SN: {}", ssrc, sn);
String redisKey = SSRC_INFO_KEY + userSetting.getServerId() + "_" + mediaServerId;
redisTemplate.opsForSet().add(redisKey, sn);
}
@ -122,4 +126,18 @@ public class SSRCFactory {
return Boolean.TRUE.equals(redisTemplate.hasKey(redisKey));
}
private String getSsrcPrefix() {
String sipDomain = sipConfig.getDomain();
return sipDomain.length() >= 8 ? sipDomain.substring(3, 8) : sipDomain;
}
private boolean isFactorySsrc(String ssrc) {
if (ssrc.length() < 2) {
return false;
}
String sn = ssrc.substring(1);
String ssrcPrefix = getSsrcPrefix();
return sn.length() == ssrcPrefix.length() + 4 && sn.startsWith(ssrcPrefix);
}
}

View File

@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.utils.EnvUtil;
import com.genersoft.iot.vmp.utils.GitUtil;
import com.genersoft.iot.vmp.utils.IpPortUtil;
import gov.nist.javax.sip.message.SIPRequest;
@ -334,6 +335,9 @@ public class SIPRequestHeaderProvider {
public Request createAckRequest(String localIp, SipURI sipURI, SIPResponse sipResponse) throws ParseException, InvalidArgumentException, PeerUnavailableException {
if(EnvUtil.isDockerEnv()){
localIp = sipLayer.getLocalIp(localIp);
}
// via
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(localIp, sipConfig.getPort(), sipResponse.getTopmostViaHeader().getTransport(), SipUtils.getNewViaTag());

View File

@ -282,21 +282,22 @@ public class SIPCommander implements ISIPCommander {
// f字段:f= v/编码格式/分辨率/帧率/码率类型/码率大小a/编码格式/码率大小/采样率
// content.append("f=v/2/6/25/1/4000a/6/8/1" + "\r\n"); // 未发现支持此特性的设备
Request request = headerProvider.createInviteRequest(device, channel.getDeviceId(), content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> {
sessionManager.removeByStream(ssrcInfo.getApp(), ssrcInfo.getStream());
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
errorEvent.response(e);
}), e -> {
ResponseEvent responseEvent = (ResponseEvent) e.event;
SIPResponse response = (SIPResponse) responseEvent.getResponse();
String callId = response.getCallIdHeader().getCallId();
SsrcTransaction ssrcTransaction = SsrcTransaction.buildForDevice(device.getDeviceId(), channel.getId(),
callId,ssrcInfo.getApp(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response,
InviteSessionType.PLAY);
sessionManager.put(ssrcTransaction);
okEvent.response(e);
}, timeout);
Request request = headerProvider.createInviteRequest(device, channel.getDeviceId(), content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> {
sessionManager.removeByStream(ssrcInfo.getApp(), ssrcInfo.getStream());
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrcToRelease());
errorEvent.response(e);
}), e -> {
ResponseEvent responseEvent = (ResponseEvent) e.event;
SIPResponse response = (SIPResponse) responseEvent.getResponse();
String callId = response.getCallIdHeader().getCallId();
SsrcTransaction ssrcTransaction = SsrcTransaction.buildForDevice(device.getDeviceId(), channel.getId(),
callId,ssrcInfo.getApp(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response,
InviteSessionType.PLAY);
ssrcTransaction.setAllocatedSsrc(ssrcInfo.getAllocatedSsrc());
sessionManager.put(ssrcTransaction);
okEvent.response(e);
}, timeout);
}
/**
@ -384,16 +385,17 @@ public class SIPCommander implements ISIPCommander {
Request request = headerProvider.createPlaybackInviteRequest(device, channel.getDeviceId(), content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()), ssrcInfo.getSsrc());
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, event -> {
ResponseEvent responseEvent = (ResponseEvent) event.event;
SIPResponse response = (SIPResponse) responseEvent.getResponse();
SsrcTransaction ssrcTransaction = SsrcTransaction.buildForDevice(device.getDeviceId(),
channel.getId(), sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),
device.getTransport()).getCallId(), ssrcInfo.getApp(), ssrcInfo.getStream(), ssrcInfo.getSsrc(),
mediaServerItem.getId(), response, InviteSessionType.PLAYBACK);
sessionManager.put(ssrcTransaction);
okEvent.response(event);
}, timeout);
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, event -> {
ResponseEvent responseEvent = (ResponseEvent) event.event;
SIPResponse response = (SIPResponse) responseEvent.getResponse();
SsrcTransaction ssrcTransaction = SsrcTransaction.buildForDevice(device.getDeviceId(),
channel.getId(), sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),
device.getTransport()).getCallId(), ssrcInfo.getApp(), ssrcInfo.getStream(), ssrcInfo.getSsrc(),
mediaServerItem.getId(), response, InviteSessionType.PLAYBACK);
ssrcTransaction.setAllocatedSsrc(ssrcInfo.getAllocatedSsrc());
sessionManager.put(ssrcTransaction);
okEvent.response(event);
}, timeout);
}
/**
@ -476,17 +478,18 @@ public class SIPCommander implements ISIPCommander {
CallIdHeader newCallIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()), device.getTransport());
Request request = headerProvider.createPlaybackInviteRequest(device, channel.getDeviceId(), content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,newCallIdHeader, ssrcInfo.getSsrc());
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, event -> {
ResponseEvent responseEvent = (ResponseEvent) event.event;
SIPResponse response = (SIPResponse) responseEvent.getResponse();
String contentString =new String(response.getRawContent());
String ssrc = SipUtils.getSsrcFromSdp(contentString);
SsrcTransaction ssrcTransaction = SsrcTransaction.buildForDevice(device.getDeviceId(), channel.getId(),
response.getCallIdHeader().getCallId(), ssrcInfo.getApp(), ssrcInfo.getStream(), ssrc,
mediaServerItem.getId(), response, InviteSessionType.DOWNLOAD);
sessionManager.put(ssrcTransaction);
okEvent.response(event);
}, timeout);
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, event -> {
ResponseEvent responseEvent = (ResponseEvent) event.event;
SIPResponse response = (SIPResponse) responseEvent.getResponse();
String contentString =new String(response.getRawContent());
String ssrc = SipUtils.getSsrcFromSdp(contentString);
SsrcTransaction ssrcTransaction = SsrcTransaction.buildForDevice(device.getDeviceId(), channel.getId(),
response.getCallIdHeader().getCallId(), ssrcInfo.getApp(), ssrcInfo.getStream(), ssrc,
mediaServerItem.getId(), response, InviteSessionType.DOWNLOAD);
ssrcTransaction.setAllocatedSsrc(ssrcInfo.getAllocatedSsrc());
sessionManager.put(ssrcTransaction);
okEvent.response(event);
}, timeout);
}
@Override
@ -540,20 +543,21 @@ public class SIPCommander implements ISIPCommander {
// f字段:f= v/编码格式/分辨率/帧率/码率类型/码率大小a/编码格式/码率大小/采样率
content.append("f=v/////a/1/8/1" + "\r\n");
Request request = headerProvider.createInviteRequest(device, channel.getDeviceId(), content.toString(),
SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, sendRtpItem.getSsrc(), callIdHeader);
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> {
sessionManager.removeByStream(sendRtpItem.getApp(), sendRtpItem.getStream());
mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc());
errorEvent.response(e);
}), e -> {
// 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值
ResponseEvent responseEvent = (ResponseEvent) e.event;
SIPResponse response = (SIPResponse) responseEvent.getResponse();
SsrcTransaction ssrcTransaction = SsrcTransaction.buildForDevice(device.getDeviceId(), channel.getId(), MediaApp.GB28181_TALK,sendRtpItem.getApp(), stream, sendRtpItem.getSsrc(), mediaServerItem.getId(), response, InviteSessionType.TALK);
sessionManager.put(ssrcTransaction);
okEvent.response(e);
}, timeout);
Request request = headerProvider.createInviteRequest(device, channel.getDeviceId(), content.toString(),
SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, sendRtpItem.getSsrc(), callIdHeader);
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, (e -> {
sessionManager.removeByStream(sendRtpItem.getApp(), sendRtpItem.getStream());
mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrcToRelease());
errorEvent.response(e);
}), e -> {
// 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值
ResponseEvent responseEvent = (ResponseEvent) e.event;
SIPResponse response = (SIPResponse) responseEvent.getResponse();
SsrcTransaction ssrcTransaction = SsrcTransaction.buildForDevice(device.getDeviceId(), channel.getId(), MediaApp.GB28181_TALK,sendRtpItem.getApp(), stream, sendRtpItem.getSsrc(), mediaServerItem.getId(), response, InviteSessionType.TALK);
ssrcTransaction.setAllocatedSsrc(sendRtpItem.getAllocatedSsrc());
sessionManager.put(ssrcTransaction);
okEvent.response(e);
}, timeout);
}
/**

View File

@ -642,7 +642,7 @@ public class SIPCommanderForPlatform implements ISIPCommanderForPlatform {
String mediaServerId = sendRtpItem.getMediaServerId();
MediaServer mediaServerItem = mediaServerService.getOne(mediaServerId);
if (mediaServerItem != null) {
mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc());
mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrcToRelease());
receiveRtpServerService.closeRTPServer(mediaServerItem, sendRtpItem.getApp(), sendRtpItem.getStream());
}
SIPRequest byeRequest = headerProviderPlatformProvider.createByeRequest(platform, sendRtpItem, channel);
@ -744,13 +744,14 @@ public class SIPCommanderForPlatform implements ISIPCommanderForPlatform {
callIdHeader);
sipSender.transmitRequest(sipLayer.getLocalIp(platform.getDeviceIp()), request, (e -> {
sessionManager.removeByStream(ssrcInfo.getApp(), ssrcInfo.getStream());
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrcToRelease());
errorEvent.response(e);
}), e -> {
ResponseEvent responseEvent = (ResponseEvent) e.event;
SIPResponse response = (SIPResponse) responseEvent.getResponse();
SsrcTransaction ssrcTransaction = SsrcTransaction.buildForPlatform(platform.getServerGBId(), channel.getGbId(),
callIdHeader.getCallId(), ssrcInfo.getApp(), stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response, InviteSessionType.BROADCAST);
ssrcTransaction.setAllocatedSsrc(ssrcInfo.getAllocatedSsrc());
sessionManager.put(ssrcTransaction);
okEvent.response(e);
});

View File

@ -132,7 +132,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
if (mediaServer != null) {
mediaServerService.stopSendRtp(mediaServer, sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getSsrc());
if (userSetting.getUseCustomSsrcForParentInvite()) {
mediaServerService.releaseSsrc(mediaServer.getId(), sendRtpItem.getSsrc());
mediaServerService.releaseSsrc(mediaServer.getId(), sendRtpItem.getSsrcToRelease());
}
}
}
@ -144,7 +144,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
sendRtpServerService.delete(sendRtpItem);
mediaServerService.stopSendRtp(mediaInfo, sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getSsrc());
if (userSetting.getUseCustomSsrcForParentInvite()) {
mediaServerService.releaseSsrc(mediaInfo.getId(), sendRtpItem.getSsrc());
mediaServerService.releaseSsrc(mediaInfo.getId(), sendRtpItem.getSsrcToRelease());
}
}
if (sendRtpItem.getServerId().equals(userSetting.getServerId())) {
@ -254,7 +254,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
// 释放ssrc
MediaServer mediaServerItem = mediaServerService.getOne(ssrcTransaction.getMediaServerId());
if (mediaServerItem != null) {
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransaction.getSsrc());
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransaction.getSsrcToRelease());
}
sessionManager.removeByCallId(ssrcTransaction.getCallId());
}

View File

@ -120,9 +120,10 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
@Override
public void process(RequestEvent evt) {
SIPRequest request = (SIPRequest)evt.getRequest();
SIPRequest request = (SIPRequest) evt.getRequest();
InviteMessageInfo inviteInfo = null;
try {
InviteMessageInfo inviteInfo = decode(evt);
inviteInfo = decode(evt);
// 查询请求是否来自上级平台\设备
Platform platform = platformService.queryPlatformByServerGBId(inviteInfo.getRequesterId());
@ -130,7 +131,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
inviteFromDeviceHandle(request, inviteInfo);
} else {
// 查询平台下是否有该通道
CommonGBChannel channel= channelService.queryOneWithPlatform(platform.getId(), inviteInfo.getTargetChannelId());
CommonGBChannel channel = channelService.queryOneWithPlatform(platform.getId(), inviteInfo.getTargetChannelId());
if (channel == null) {
log.info("[上级INVITE] 通道不存在返回404: {}", inviteInfo.getTargetChannelId());
try {
@ -143,9 +144,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
}
log.info("[上级INVITE] 平台:{} 通道:{}({}), 收流地址:{}:{},收流方式:{}, 点播类型:{}, SSRC{}",
platform.getName(), channel.getGbName(), channel.getGbDeviceId(), inviteInfo.getIp(),
inviteInfo.getPort(), inviteInfo.isTcp()?(inviteInfo.isTcpActive()?"TCP主动":"TCP被动"): "UDP",
inviteInfo.getPort(), inviteInfo.isTcp() ? (inviteInfo.isTcpActive() ? "TCP主动" : "TCP被动") : "UDP",
inviteInfo.getSessionName(), inviteInfo.getSsrc());
if(!userSetting.getUseCustomSsrcForParentInvite() && ObjectUtils.isEmpty(inviteInfo.getSsrc())) {
if (!userSetting.getUseCustomSsrcForParentInvite() && ObjectUtils.isEmpty(inviteInfo.getSsrc())) {
log.warn("[上级INVITE] 点播失败, 上级未携带SSRC, 并且本级未设置使用自定义SSRC");
// 通道存在发100TRYING
try {
@ -162,50 +163,54 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
log.error("[命令发送失败] 上级INVITE TRYING: {}", e.getMessage());
}
InviteMessageInfo finalInviteInfo = inviteInfo;
channelPlayService.startInvite(channel, inviteInfo, platform, ((code, msg, streamInfo) -> {
if (code != InviteErrorCode.SUCCESS.getCode()) {
try {
responseAck(request, Response.BUSY_HERE , msg);
responseAck(request, Response.BUSY_HERE, msg);
} catch (SipException | InvalidArgumentException | ParseException e) {
log.error("[命令发送失败] 上级INVITE 点播失败: {}", e.getMessage());
}
}else {
} else {
// 点播成功 TODO 可以在此处检测cancel命令是否存在存在则不发送
if (userSetting.getUseCustomSsrcForParentInvite()) {
// 上级平台点播时不使用上级平台指定的ssrc使用自定义的ssrc参考国标文档-点播外域设备媒体流SSRC处理方式
MediaServer mediaServer = mediaServerService.getOne(streamInfo.getMediaServer().getId());
if (mediaServer != null) {
String ssrc = "Play".equalsIgnoreCase(inviteInfo.getSessionName())
String ssrc = "Play".equalsIgnoreCase(finalInviteInfo.getSessionName())
? ssrcFactory.getPlaySsrc(streamInfo.getMediaServer().getId())
: ssrcFactory.getPlayBackSsrc(streamInfo.getMediaServer().getId());
inviteInfo.setSsrc(ssrc);
finalInviteInfo.setSsrc(ssrc);
finalInviteInfo.setAllocatedSsrc(ssrc);
finalInviteInfo.setAllocatedSsrcMediaServerId(streamInfo.getMediaServer().getId());
}
}
// 构建sendRTP内容
SendRtpInfo sendRtpItem = sendRtpServerService.createSendRtpInfo(streamInfo.getMediaServer(),
inviteInfo.getIp(), inviteInfo.getPort(), inviteInfo.getSsrc(), platform.getServerGBId(),
finalInviteInfo.getIp(), finalInviteInfo.getPort(), finalInviteInfo.getSsrc(), platform.getServerGBId(),
streamInfo.getApp(), streamInfo.getStream(),
channel.getGbId(), inviteInfo.isTcp(), platform.isRtcp());
if (inviteInfo.isTcp() && inviteInfo.isTcpActive()) {
channel.getGbId(), finalInviteInfo.isTcp(), platform.isRtcp());
sendRtpItem.setAllocatedSsrc(finalInviteInfo.getAllocatedSsrc());
if (finalInviteInfo.isTcp() && finalInviteInfo.isTcpActive()) {
sendRtpItem.setTcpActive(true);
}
sendRtpItem.setStatus(1);
sendRtpItem.setCallId(inviteInfo.getCallId());
sendRtpItem.setCallId(finalInviteInfo.getCallId());
sendRtpItem.setPlayTypeByChannelDataType(channel.getDataType(), inviteInfo.getSessionName());
sendRtpItem.setPlayTypeByChannelDataType(channel.getDataType(), finalInviteInfo.getSessionName());
sendRtpItem.setServerId(streamInfo.getServerId());
sendRtpServerService.update(sendRtpItem);
String sdpIp = streamInfo.getMediaServer().getSdpIp();
if (!ObjectUtils.isEmpty(platform.getSendStreamIp())) {
sdpIp = platform.getSendStreamIp();
}
String content = createSendSdp(sendRtpItem, inviteInfo, sdpIp);
String content = createSendSdp(sendRtpItem, finalInviteInfo, sdpIp);
// 超时未收到Ack应该回复bye,当前等待时间为10秒
dynamicTask.startDelay(inviteInfo.getCallId(), () -> {
log.info("[Ack ] 等待超时, {}/{}", inviteInfo.getCallId(), channel.getGbDeviceId());
mediaServerService.releaseSsrc(streamInfo.getMediaServer().getId(), sendRtpItem.getSsrc());
dynamicTask.startDelay(finalInviteInfo.getCallId(), () -> {
log.info("[Ack ] 等待超时, {}/{}", finalInviteInfo.getCallId(), channel.getGbDeviceId());
mediaServerService.releaseSsrc(streamInfo.getMediaServer().getId(), sendRtpItem.getSsrcToRelease());
// 回复bye
sendBye(platform, inviteInfo.getCallId());
sendBye(platform, finalInviteInfo.getCallId());
}, 60 * 1000);
try {
responseSdpAck(request, content, platform);
@ -222,9 +227,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
if (deviceChannel != null) {
redisCatchStorage.sendPlatformStartPlayMsg(sendRtpItem, deviceChannel, platform);
}
}catch (ControllerException e) {
} catch (ControllerException e) {
log.warn("[上级INVITE] tcp主动模式 发流失败", e);
sendBye(platform, inviteInfo.getCallId());
sendBye(platform, finalInviteInfo.getCallId());
}
}
}
@ -243,14 +248,16 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
} catch (SipException | InvalidArgumentException | ParseException sendException) {
log.error("[命令发送失败] invite BAD_REQUEST: {}", sendException.getMessage());
}
}catch (PlayException e) {
} catch (PlayException e) {
releaseAllocatedSsrc(inviteInfo);
try {
responseAck(request, e.getCode(), e.getMsg());
} catch (SipException | InvalidArgumentException | ParseException sendException) {
log.error("[命令发送失败] invite 点播失败: {}", sendException.getMessage());
}
}catch (Exception e) {
} catch (Exception e) {
log.error("[Invite处理异常] ", e);
releaseAllocatedSsrc(inviteInfo);
try {
responseAck(request, Response.SERVER_INTERNAL_ERROR, "");
} catch (SipException | InvalidArgumentException | ParseException sendException) {
@ -259,6 +266,15 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
}
}
private void releaseAllocatedSsrc(InviteMessageInfo inviteInfo) {
if (inviteInfo == null || inviteInfo.getAllocatedSsrc() == null || inviteInfo.getAllocatedSsrcMediaServerId() == null) {
return;
}
mediaServerService.releaseSsrc(inviteInfo.getAllocatedSsrcMediaServerId(), inviteInfo.getAllocatedSsrc());
inviteInfo.setAllocatedSsrc(null);
inviteInfo.setAllocatedSsrcMediaServerId(null);
}
private InviteMessageInfo decode(RequestEvent evt) throws SdpException {
InviteMessageInfo inviteInfo = new InviteMessageInfo();

View File

@ -7,6 +7,7 @@ public class SSRCInfo {
private int port;
private String ssrc;
private String allocatedSsrc;
private String app;
private String Stream;
@ -17,4 +18,8 @@ public class SSRCInfo {
this.Stream = stream;
}
public String getSsrcToRelease() {
return allocatedSsrc;
}
}

View File

@ -102,6 +102,9 @@ public class RtpServerServiceImpl implements IReceiveRtpServerService {
}
SSRCInfo ssrcInfo = new SSRCInfo(0, ssrc, MediaApp.GB28181, streamId);
if (presetSSRC == null) {
ssrcInfo.setAllocatedSsrc(ssrc);
}
RTPServerParam rtpServerParam = new RTPServerParam(mediaServer, MediaApp.GB28181, streamId, ssrcCheck ? Long.parseLong(ssrc): 0L, null, onlyAuto, disableAuto, false, tcpMode);
int rtpServerPort = openRTPServer(rtpServerParam, ((code, msg, data) -> {
if (code == InviteErrorCode.SUCCESS.getCode()) {
@ -113,6 +116,7 @@ public class RtpServerServiceImpl implements IReceiveRtpServerService {
// 释放ssrc
if (presetSSRC == null) {
ssrcFactory.releaseSsrc(mediaServer.getId(), ssrc);
ssrcInfo.setAllocatedSsrc(null);
}
OpenRTPServerResult openRTPServerResult = new OpenRTPServerResult();
openRTPServerResult.setSsrcInfo(ssrcInfo);

View File

@ -56,6 +56,7 @@ public class RedisRpcSendRtpController extends RpcController {
if (mediaServerItem == null) {
RedisRpcResponse response = request.getResponse();
response.setStatusCode(ErrorCode.SUCCESS.getCode());
return response;
}
// 自平台内容
int localPort = sendRtpServerService.getNextPort(mediaServerItem);
@ -63,6 +64,7 @@ public class RedisRpcSendRtpController extends RpcController {
log.info("[redis-rpc] getSendRtpItem->服务器端口资源不足" );
RedisRpcResponse response = request.getResponse();
response.setStatusCode(ErrorCode.SUCCESS.getCode());
return response;
}
// 写入redis 超时时回复
sendRtpItem.setStatus(1);
@ -72,6 +74,7 @@ public class RedisRpcSendRtpController extends RpcController {
// 上级平台点播时不使用上级平台指定的ssrc使用自定义的ssrc参考国标文档-点播外域设备媒体流SSRC处理方式
String ssrc = "Play".equalsIgnoreCase(sendRtpItem.getSessionName()) ? ssrcFactory.getPlaySsrc(mediaServerItem.getId()) : ssrcFactory.getPlayBackSsrc(mediaServerItem.getId());
sendRtpItem.setSsrc(ssrc);
sendRtpItem.setAllocatedSsrc(ssrc);
}
sendRtpServerService.update(sendRtpItem);
RedisRpcResponse response = request.getResponse();
@ -99,6 +102,7 @@ public class RedisRpcSendRtpController extends RpcController {
MediaServer mediaServer = mediaServerService.getOne(sendRtpItem.getMediaServerId());
if (mediaServer == null) {
log.info("[redis-rpc] startSendRtp->未找到MediaServer {}", sendRtpItem.getMediaServerId() );
clearSendRtpItem(sendRtpItem);
WVPResult wvpResult = WVPResult.fail(ErrorCode.ERROR100.getCode(), "未找到MediaServer");
response.setBody(wvpResult);
return response;
@ -106,6 +110,7 @@ public class RedisRpcSendRtpController extends RpcController {
MediaInfo mediaInfo = mediaServerService.getMediaInfo(mediaServer, sendRtpItem.getApp(), sendRtpItem.getStream());
if (mediaInfo == null) {
log.info("[redis-rpc] startSendRtp->流不在线: {}/{}", sendRtpItem.getApp(), sendRtpItem.getStream() );
clearSendRtpItem(sendRtpItem);
WVPResult wvpResult = WVPResult.fail(ErrorCode.ERROR100.getCode(), "流不在线");
response.setBody(wvpResult);
return response;
@ -114,6 +119,7 @@ public class RedisRpcSendRtpController extends RpcController {
mediaServerService.startSendRtp(mediaServer, sendRtpItem);
}catch (ControllerException exception) {
log.info("[redis-rpc] 发流失败: {}/{}, 目标地址: {}{} {}", sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort(), exception.getMsg());
clearSendRtpItem(sendRtpItem);
WVPResult wvpResult = WVPResult.fail(exception.getCode(), exception.getMsg());
response.setBody(wvpResult);
return response;
@ -143,6 +149,7 @@ public class RedisRpcSendRtpController extends RpcController {
MediaServer mediaServer = mediaServerService.getOne(sendRtpItem.getMediaServerId());
if (mediaServer == null) {
log.info("[redis-rpc] stopSendRtp->未找到MediaServer {}", sendRtpItem.getMediaServerId() );
clearSendRtpItem(sendRtpItem);
WVPResult wvpResult = WVPResult.fail(ErrorCode.ERROR100.getCode(), "未找到MediaServer");
response.setBody(wvpResult);
return response;
@ -155,9 +162,20 @@ public class RedisRpcSendRtpController extends RpcController {
response.setBody(WVPResult.fail(exception.getCode(), exception.getMsg()));
return response;
}
clearSendRtpItem(sendRtpItem);
log.info("[redis-rpc] 停止推流成功: {}/{}, 目标地址: {}{}", sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort() );
response.setBody(WVPResult.success());
return response;
}
private void clearSendRtpItem(SendRtpInfo sendRtpItem) {
if (sendRtpItem == null) {
return;
}
sendRtpServerService.delete(sendRtpItem);
if (sendRtpItem.getMediaServerId() != null) {
mediaServerService.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrcToRelease());
}
}
}

View File

@ -76,6 +76,7 @@ public class RedisRpcStreamPushController extends RpcController {
// 上级平台点播时不使用上级平台指定的ssrc使用自定义的ssrc参考国标文档-点播外域设备媒体流SSRC处理方式
String ssrc = "Play".equalsIgnoreCase(sendRtpItem.getSessionName()) ? ssrcFactory.getPlaySsrc(mediaServer.getId()) : ssrcFactory.getPlayBackSsrc(mediaServer.getId());
sendRtpItem.setSsrc(ssrc);
sendRtpItem.setAllocatedSsrc(ssrc);
}
sendRtpItem.setMediaServerId(mediaServer.getId());
sendRtpItem.setLocalIp(mediaServer.getSdpIp());
@ -95,6 +96,7 @@ public class RedisRpcStreamPushController extends RpcController {
// 上级平台点播时不使用上级平台指定的ssrc使用自定义的ssrc参考国标文档-点播外域设备媒体流SSRC处理方式
String ssrc = "Play".equalsIgnoreCase(sendRtpItem.getSessionName()) ? ssrcFactory.getPlaySsrc(hookData.getMediaServer().getId()) : ssrcFactory.getPlayBackSsrc(hookData.getMediaServer().getId());
sendRtpItem.setSsrc(ssrc);
sendRtpItem.setAllocatedSsrc(ssrc);
}
sendRtpItem.setMediaServerId(hookData.getMediaServer().getId());
sendRtpItem.setLocalIp(hookData.getMediaServer().getSdpIp());

View File

@ -110,6 +110,7 @@ public class RedisRpcServiceImpl implements IRedisRpcService {
// 上级平台点播时不使用上级平台指定的ssrc使用自定义的ssrc参考国标文档-点播外域设备媒体流SSRC处理方式
String ssrc = "Play".equalsIgnoreCase(sendRtpItem.getSessionName()) ? ssrcFactory.getPlaySsrc(hookData.getMediaServer().getId()) : ssrcFactory.getPlayBackSsrc(hookData.getMediaServer().getId());
sendRtpItem.setSsrc(ssrc);
sendRtpItem.setAllocatedSsrc(ssrc);
}
sendRtpItem.setMediaServerId(hookData.getMediaServer().getId());
sendRtpItem.setLocalIp(hookData.getMediaServer().getSdpIp());

View File

@ -0,0 +1,8 @@
package com.genersoft.iot.vmp.utils;
public class EnvUtil {
public static boolean isDockerEnv() {
return "docker".equals(System.getenv("RUN_ENV"));
}
}

View File

@ -861,7 +861,7 @@
320623,如东县,3206
320681,启东市,3206
320682,如皋市,3206
320684,海门,3206
320684,海门,3206
320685,海安市,3206
3207,连云港市,32
320703,连云区,3207
@ -918,8 +918,6 @@
33,浙江省,
3301,杭州市,33
330102,上城区,3301
330103,下城区,3301
330104,江干区,3301
330105,拱墅区,3301
330106,西湖区,3301
330108,滨江区,3301
@ -927,6 +925,8 @@
330110,余杭区,3301
330111,富阳区,3301
330112,临安区,3301
330113,临平区,3301
330114,钱塘区,3301
330122,桐庐县,3301
330127,淳安县,3301
330182,建德市,3301

1 编号 名称 上级
861 320623 如东县 3206
862 320681 启东市 3206
863 320682 如皋市 3206
864 320684 海门市 海门区 3206
865 320685 海安市 3206
866 3207 连云港市 32
867 320703 连云区 3207
918 33 浙江省
919 3301 杭州市 33
920 330102 上城区 3301
330103 下城区 3301
330104 江干区 3301
921 330105 拱墅区 3301
922 330106 西湖区 3301
923 330108 滨江区 3301
925 330110 余杭区 3301
926 330111 富阳区 3301
927 330112 临安区 3301
928 330113 临平区 3301
929 330114 钱塘区 3301
930 330122 桐庐县 3301
931 330127 淳安县 3301
932 330182 建德市 3301

View File

@ -101,6 +101,7 @@ sip:
# 请不要使用127.0.0.1任何包括localhost在内的域名都是不可以的。
ip: 0.0.0.0
# [可选] 没有任何业务需求,仅仅是在前端展示的时候用
# [docker环境下必选] 在docker环境中运行时此配置为sip对外的ip地址 必须配置,否则无法正常使用
show-ip: 192.168.0.100
# [可选] 28181服务监听的端口
port: 5060