收流时设置re_use_port参数解决端口关闭快速打开造成的端口未释放问题, 支持点播的tcp主动
This commit is contained in:
parent
f68f6d20e0
commit
0f3898910c
@ -247,6 +247,17 @@ public class Device {
|
|||||||
return streamMode;
|
return streamMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getStreamModeForParam() {
|
||||||
|
if (streamMode.equalsIgnoreCase("UDP")) {
|
||||||
|
return 0;
|
||||||
|
}else if (streamMode.equalsIgnoreCase("TCP-PASSIVE")) {
|
||||||
|
return 1;
|
||||||
|
}else if (streamMode.equalsIgnoreCase("TCP-ACTIVE")) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public void setStreamMode(String streamMode) {
|
public void setStreamMode(String streamMode) {
|
||||||
this.streamMode = streamMode;
|
this.streamMode = streamMode;
|
||||||
}
|
}
|
||||||
|
@ -425,7 +425,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
|||||||
sendRtpItem.setApp("rtp");
|
sendRtpItem.setApp("rtp");
|
||||||
if ("Playback".equalsIgnoreCase(sessionName)) {
|
if ("Playback".equalsIgnoreCase(sessionName)) {
|
||||||
sendRtpItem.setPlayType(InviteStreamType.PLAYBACK);
|
sendRtpItem.setPlayType(InviteStreamType.PLAYBACK);
|
||||||
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, device.isSsrcCheck(), true);
|
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, null, device.isSsrcCheck(), true, 0, false, device.getStreamModeForParam());
|
||||||
sendRtpItem.setStreamId(ssrcInfo.getStream());
|
sendRtpItem.setStreamId(ssrcInfo.getStream());
|
||||||
// 写入redis, 超时时回复
|
// 写入redis, 超时时回复
|
||||||
redisCatchStorage.updateSendRTPSever(sendRtpItem);
|
redisCatchStorage.updateSendRTPSever(sendRtpItem);
|
||||||
@ -469,7 +469,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
|||||||
if (mediaServerItem.isRtpEnable()) {
|
if (mediaServerItem.isRtpEnable()) {
|
||||||
streamId = String.format("%s_%s", device.getDeviceId(), channelId);
|
streamId = String.format("%s_%s", device.getDeviceId(), channelId);
|
||||||
}
|
}
|
||||||
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, device.isSsrcCheck(), false);
|
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, device.isSsrcCheck(), false, 0, false, device.getStreamModeForParam());
|
||||||
logger.info(JSONObject.toJSONString(ssrcInfo));
|
logger.info(JSONObject.toJSONString(ssrcInfo));
|
||||||
sendRtpItem.setStreamId(ssrcInfo.getStream());
|
sendRtpItem.setStreamId(ssrcInfo.getStream());
|
||||||
sendRtpItem.setSsrc(ssrc.equals(ssrcDefault) ? ssrcInfo.getSsrc() : ssrc);
|
sendRtpItem.setSsrc(ssrc.equals(ssrcDefault) ? ssrcInfo.getSsrc() : ssrc);
|
||||||
|
@ -346,4 +346,12 @@ public class ZLMRESTfulUtils {
|
|||||||
param.put("stream_id", streamId);
|
param.put("stream_id", streamId);
|
||||||
return sendPost(mediaServerItem, "resumeRtpCheck",param, null);
|
return sendPost(mediaServerItem, "resumeRtpCheck",param, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JSONObject connectRtpServer(MediaServerItem mediaServerItem, String dst_url, int dst_port, String stream_id) {
|
||||||
|
Map<String, Object> param = new HashMap<>(1);
|
||||||
|
param.put("dst_url", dst_url);
|
||||||
|
param.put("dst_port", dst_port);
|
||||||
|
param.put("stream_id", stream_id);
|
||||||
|
return sendPost(mediaServerItem, "connectRtpServer",param, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,17 @@ public class ZLMRTPServerFactory {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int createRTPServer(MediaServerItem mediaServerItem, String streamId, int ssrc, Integer port) {
|
/**
|
||||||
|
* 开启rtpServer
|
||||||
|
* @param mediaServerItem zlm服务实例
|
||||||
|
* @param streamId 流Id
|
||||||
|
* @param ssrc ssrc
|
||||||
|
* @param port 端口, 0/null为使用随机
|
||||||
|
* @param reUsePort 是否重用端口
|
||||||
|
* @param tcpMode 0/null udp 模式,1 tcp 被动模式, 2 tcp 主动模式。
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int createRTPServer(MediaServerItem mediaServerItem, String streamId, int ssrc, Integer port, Boolean reUsePort, Integer tcpMode) {
|
||||||
int result = -1;
|
int result = -1;
|
||||||
// 查询此rtp server 是否已经存在
|
// 查询此rtp server 是否已经存在
|
||||||
JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaServerItem, streamId);
|
JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaServerItem, streamId);
|
||||||
@ -107,7 +117,7 @@ public class ZLMRTPServerFactory {
|
|||||||
JSONObject jsonObject = zlmresTfulUtils.closeRtpServer(mediaServerItem, param);
|
JSONObject jsonObject = zlmresTfulUtils.closeRtpServer(mediaServerItem, param);
|
||||||
if (jsonObject != null ) {
|
if (jsonObject != null ) {
|
||||||
if (jsonObject.getInteger("code") == 0) {
|
if (jsonObject.getInteger("code") == 0) {
|
||||||
return createRTPServer(mediaServerItem, streamId, ssrc, port);
|
return createRTPServer(mediaServerItem, streamId, ssrc, port, reUsePort, tcpMode);
|
||||||
}else {
|
}else {
|
||||||
logger.warn("[开启rtpServer], 重启RtpServer错误");
|
logger.warn("[开启rtpServer], 重启RtpServer错误");
|
||||||
}
|
}
|
||||||
@ -121,8 +131,14 @@ public class ZLMRTPServerFactory {
|
|||||||
|
|
||||||
Map<String, Object> param = new HashMap<>();
|
Map<String, Object> param = new HashMap<>();
|
||||||
|
|
||||||
param.put("enable_tcp", 1);
|
if (tcpMode == null) {
|
||||||
|
tcpMode = 0;
|
||||||
|
}
|
||||||
|
param.put("tcp_mode", tcpMode);
|
||||||
param.put("stream_id", streamId);
|
param.put("stream_id", streamId);
|
||||||
|
if (reUsePort != null) {
|
||||||
|
param.put("re_use_port", reUsePort?"1":"0");
|
||||||
|
}
|
||||||
// 推流端口设置0则使用随机端口
|
// 推流端口设置0则使用随机端口
|
||||||
if (port == null) {
|
if (port == null) {
|
||||||
param.put("port", 0);
|
param.put("port", 0);
|
||||||
|
@ -44,11 +44,8 @@ public interface IMediaServerService {
|
|||||||
|
|
||||||
void updateVmServer(List<MediaServerItem> mediaServerItemList);
|
void updateVmServer(List<MediaServerItem> mediaServerItemList);
|
||||||
|
|
||||||
SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean ssrcCheck, boolean isPlayback);
|
SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck,
|
||||||
|
boolean isPlayback, Integer port, Boolean reUsePort, Integer tcpMode);
|
||||||
SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback);
|
|
||||||
|
|
||||||
SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback, Integer port);
|
|
||||||
|
|
||||||
void closeRTPServer(MediaServerItem mediaServerItem, String streamId);
|
void closeRTPServer(MediaServerItem mediaServerItem, String streamId);
|
||||||
|
|
||||||
|
@ -125,13 +125,10 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean ssrcCheck, boolean isPlayback) {
|
|
||||||
return openRTPServer(mediaServerItem, streamId, null, ssrcCheck,isPlayback);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String presetSsrc, boolean ssrcCheck, boolean isPlayback, Integer port) {
|
public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String presetSsrc, boolean ssrcCheck,
|
||||||
|
boolean isPlayback, Integer port, Boolean reUsePort, Integer tcpMode) {
|
||||||
if (mediaServerItem == null || mediaServerItem.getId() == null) {
|
if (mediaServerItem == null || mediaServerItem.getId() == null) {
|
||||||
logger.info("[openRTPServer] 失败, mediaServerItem == null || mediaServerItem.getId() == null");
|
logger.info("[openRTPServer] 失败, mediaServerItem == null || mediaServerItem.getId() == null");
|
||||||
return null;
|
return null;
|
||||||
@ -153,18 +150,13 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
|||||||
}
|
}
|
||||||
int rtpServerPort;
|
int rtpServerPort;
|
||||||
if (mediaServerItem.isRtpEnable()) {
|
if (mediaServerItem.isRtpEnable()) {
|
||||||
rtpServerPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId, ssrcCheck?Integer.parseInt(ssrc):0, port);
|
rtpServerPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId, ssrcCheck?Integer.parseInt(ssrc):0, port, reUsePort, tcpMode);
|
||||||
} else {
|
} else {
|
||||||
rtpServerPort = mediaServerItem.getRtpProxyPort();
|
rtpServerPort = mediaServerItem.getRtpProxyPort();
|
||||||
}
|
}
|
||||||
return new SSRCInfo(rtpServerPort, ssrc, streamId);
|
return new SSRCInfo(rtpServerPort, ssrc, streamId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback) {
|
|
||||||
return openRTPServer(mediaServerItem, streamId, ssrc, ssrcCheck, isPlayback, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void closeRTPServer(MediaServerItem mediaServerItem, String streamId) {
|
public void closeRTPServer(MediaServerItem mediaServerItem, String streamId) {
|
||||||
if (mediaServerItem == null) {
|
if (mediaServerItem == null) {
|
||||||
|
@ -43,6 +43,7 @@ import org.springframework.data.redis.core.RedisTemplate;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
|
import javax.sdp.*;
|
||||||
import javax.sip.InvalidArgumentException;
|
import javax.sip.InvalidArgumentException;
|
||||||
import javax.sip.ResponseEvent;
|
import javax.sip.ResponseEvent;
|
||||||
import javax.sip.SipException;
|
import javax.sip.SipException;
|
||||||
@ -51,6 +52,7 @@ import java.math.RoundingMode;
|
|||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
@SuppressWarnings(value = {"rawtypes", "unchecked"})
|
@SuppressWarnings(value = {"rawtypes", "unchecked"})
|
||||||
@Service
|
@Service
|
||||||
@ -180,7 +182,7 @@ public class PlayServiceImpl implements IPlayService {
|
|||||||
if (mediaServerItem.isRtpEnable()) {
|
if (mediaServerItem.isRtpEnable()) {
|
||||||
streamId = String.format("%s_%s", device.getDeviceId(), channelId);
|
streamId = String.format("%s_%s", device.getDeviceId(), channelId);
|
||||||
}
|
}
|
||||||
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, device.isSsrcCheck(), false);
|
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, device.isSsrcCheck(), false, 0, false, device.getStreamModeForParam());
|
||||||
if (ssrcInfo == null) {
|
if (ssrcInfo == null) {
|
||||||
WVPResult wvpResult = new WVPResult();
|
WVPResult wvpResult = new WVPResult();
|
||||||
wvpResult.setCode(ErrorCode.ERROR100.getCode());
|
wvpResult.setCode(ErrorCode.ERROR100.getCode());
|
||||||
@ -296,6 +298,29 @@ public class PlayServiceImpl implements IPlayService {
|
|||||||
String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12).trim();
|
String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12).trim();
|
||||||
// 查询到ssrc不一致且开启了ssrc校验则需要针对处理
|
// 查询到ssrc不一致且开启了ssrc校验则需要针对处理
|
||||||
if (ssrcInfo.getSsrc().equals(ssrcInResponse)) {
|
if (ssrcInfo.getSsrc().equals(ssrcInResponse)) {
|
||||||
|
if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE")) {
|
||||||
|
String substring = contentString.substring(0, contentString.indexOf("y="));
|
||||||
|
try {
|
||||||
|
SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring);
|
||||||
|
int port = -1;
|
||||||
|
Vector mediaDescriptions = sdp.getMediaDescriptions(true);
|
||||||
|
for (Object description : mediaDescriptions) {
|
||||||
|
MediaDescription mediaDescription = (MediaDescription) description;
|
||||||
|
Media media = mediaDescription.getMedia();
|
||||||
|
|
||||||
|
Vector mediaFormats = media.getMediaFormats(false);
|
||||||
|
if (mediaFormats.contains("96")) {
|
||||||
|
port = media.getMediaPort();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.info("[点播-TCP主动连接对方] deviceId: {}, channelId: {}, 连接对方的地址:{}:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, sdp.getConnection().getAddress(), port, device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck());
|
||||||
|
JSONObject jsonObject = zlmresTfulUtils.connectRtpServer(mediaServerItem, sdp.getConnection().getAddress(), port, ssrcInfo.getStream());
|
||||||
|
logger.info("[点播-TCP主动连接对方] 结果: {}", jsonObject);
|
||||||
|
} catch (SdpException e) {
|
||||||
|
logger.error("[点播-TCP主动连接对方] deviceId: {}, channelId: {}, 解析200OK的SDP信息失败", device.getDeviceId(), channelId, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
logger.info("[点播消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse);
|
logger.info("[点播消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse);
|
||||||
@ -331,7 +356,7 @@ public class PlayServiceImpl implements IPlayService {
|
|||||||
mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream(), result->{
|
mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream(), result->{
|
||||||
if (result) {
|
if (result) {
|
||||||
// 重新开启ssrc server
|
// 重新开启ssrc server
|
||||||
mediaServerService.openRTPServer(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), false, ssrcInfo.getPort());
|
mediaServerService.openRTPServer(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), false, ssrcInfo.getPort(), true, device.getStreamModeForParam());
|
||||||
}else {
|
}else {
|
||||||
try {
|
try {
|
||||||
logger.warn("[停止点播] {}/{}", device.getDeviceId(), channelId);
|
logger.warn("[停止点播] {}/{}", device.getDeviceId(), channelId);
|
||||||
@ -475,8 +500,7 @@ public class PlayServiceImpl implements IPlayService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MediaServerItem newMediaServerItem = getNewMediaServerItem(device);
|
MediaServerItem newMediaServerItem = getNewMediaServerItem(device);
|
||||||
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, device.isSsrcCheck(), true);
|
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, null, device.isSsrcCheck(), true, 0, false, device.getStreamModeForParam());
|
||||||
|
|
||||||
playBack(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, inviteStreamCallback, callback);
|
playBack(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, inviteStreamCallback, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -595,7 +619,7 @@ public class PlayServiceImpl implements IPlayService {
|
|||||||
mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream(), result->{
|
mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream(), result->{
|
||||||
if (result) {
|
if (result) {
|
||||||
// 重新开启ssrc server
|
// 重新开启ssrc server
|
||||||
mediaServerService.openRTPServer(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), true, ssrcInfo.getPort());
|
mediaServerService.openRTPServer(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), true, ssrcInfo.getPort(), true, device.getStreamModeForParam());
|
||||||
}else {
|
}else {
|
||||||
try {
|
try {
|
||||||
logger.warn("[回放消息]停止 {}/{}", device.getDeviceId(), channelId);
|
logger.warn("[回放消息]停止 {}/{}", device.getDeviceId(), channelId);
|
||||||
@ -645,8 +669,7 @@ public class PlayServiceImpl implements IPlayService {
|
|||||||
playBackCallback.call(downloadResult);
|
playBackCallback.call(downloadResult);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, device.isSsrcCheck(), true);
|
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, null, device.isSsrcCheck(), true, 0, false, device.getStreamModeForParam());
|
||||||
|
|
||||||
download(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, downloadSpeed, infoCallBack, playBackCallback);
|
download(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, downloadSpeed, infoCallBack, playBackCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -755,7 +778,7 @@ public class PlayServiceImpl implements IPlayService {
|
|||||||
mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream(), result->{
|
mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream(), result->{
|
||||||
if (result) {
|
if (result) {
|
||||||
// 重新开启ssrc server
|
// 重新开启ssrc server
|
||||||
mediaServerService.openRTPServer(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), true, ssrcInfo.getPort());
|
mediaServerService.openRTPServer(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), true, ssrcInfo.getPort(), true, device.getStreamModeForParam());
|
||||||
}else {
|
}else {
|
||||||
try {
|
try {
|
||||||
logger.warn("[录像下载] 停止{}/{}", device.getDeviceId(), channelId);
|
logger.warn("[录像下载] 停止{}/{}", device.getDeviceId(), channelId);
|
||||||
|
@ -25,11 +25,13 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="manufacturer" label="厂家" min-width="120" >
|
<el-table-column prop="manufacturer" label="厂家" min-width="120" >
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column prop="transport" label="信令传输模式" min-width="120" >
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="流传输模式" min-width="160" >
|
<el-table-column label="流传输模式" min-width="160" >
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-select size="mini" @change="transportChange(scope.row)" v-model="scope.row.streamMode" placeholder="请选择" style="width: 120px">
|
<el-select size="mini" @change="transportChange(scope.row)" v-model="scope.row.streamMode" placeholder="请选择" style="width: 120px">
|
||||||
<el-option key="UDP" label="UDP" value="UDP"></el-option>
|
<el-option key="UDP" label="UDP" value="UDP"></el-option>
|
||||||
<el-option key="TCP-ACTIVE" label="TCP主动模式" :disabled="true" value="TCP-ACTIVE"></el-option>
|
<el-option key="TCP-ACTIVE" label="TCP主动模式" value="TCP-ACTIVE"></el-option>
|
||||||
<el-option key="TCP-PASSIVE" label="TCP被动模式" value="TCP-PASSIVE"></el-option>
|
<el-option key="TCP-PASSIVE" label="TCP被动模式" value="TCP-PASSIVE"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</template>
|
</template>
|
||||||
|
Loading…
Reference in New Issue
Block a user