Merge branch '648540858:wvp-28181-2.0' into wvp-28181-2.0

pull/491/head
mk1990 2022-05-05 08:43:10 +08:00 committed by GitHub
commit 05a324a07a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 86 additions and 27 deletions

View File

@ -136,4 +136,7 @@ public class SsrcConfig {
this.notUsed = notUsed; this.notUsed = notUsed;
} }
public boolean checkSsrc(String ssrcInResponse) {
return !isUsed.contains(ssrcInResponse);
}
} }

View File

@ -93,7 +93,7 @@ public interface ISIPCommander {
* @param device * @param device
* @param channelId * @param channelId
*/ */
void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent); void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent);
/** /**
* *

View File

@ -343,7 +343,7 @@ public class SIPCommander implements ISIPCommander {
*/ */
@Override @Override
public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent) { ZLMHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) {
String streamId = ssrcInfo.getStream(); String streamId = ssrcInfo.getStream();
try { try {
if (device == null) return; if (device == null) return;
@ -436,6 +436,7 @@ public class SIPCommander implements ISIPCommander {
// 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值 // 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值
streamSession.put(device.getDeviceId(), channelId ,"play", streamId, ssrcInfo.getSsrc(), mediaServerItem.getId(), ((ResponseEvent)e.event).getClientTransaction(), VideoStreamSessionManager.SessionType.play); streamSession.put(device.getDeviceId(), channelId ,"play", streamId, ssrcInfo.getSsrc(), mediaServerItem.getId(), ((ResponseEvent)e.event).getClientTransaction(), VideoStreamSessionManager.SessionType.play);
streamSession.put(device.getDeviceId(), channelId ,"play", e.dialog); streamSession.put(device.getDeviceId(), channelId ,"play", e.dialog);
okEvent.response(e);
}); });

View File

@ -202,6 +202,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
String platformId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); String platformId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
String deviceID = XmlUtil.getText(rootElement, "DeviceID"); String deviceID = XmlUtil.getText(rootElement, "DeviceID");
ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId); ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId);
if (platform == null)return;
SubscribeInfo subscribeInfo = new SubscribeInfo(evt, platformId); SubscribeInfo subscribeInfo = new SubscribeInfo(evt, platformId);
if (evt.getServerTransaction() == null) { if (evt.getServerTransaction() == null) {
ServerTransaction serverTransaction = platform.getTransport().equals("TCP") ? tcpSipProvider.getNewServerTransaction(evt.getRequest()) ServerTransaction serverTransaction = platform.getTransport().equals("TCP") ? tcpSipProvider.getNewServerTransaction(evt.getRequest())

View File

@ -222,7 +222,24 @@ public class XmlUtil {
// 由于海康会错误的发送65535作为这里的取值,所以这里除非是0否则认为是1 // 由于海康会错误的发送65535作为这里的取值,所以这里除非是0否则认为是1
deviceChannel.setParental(Integer.parseInt(XmlUtil.getText(itemDevice, "Parental")) == 1?1:0); deviceChannel.setParental(Integer.parseInt(XmlUtil.getText(itemDevice, "Parental")) == 1?1:0);
} }
deviceChannel.setParentId(XmlUtil.getText(itemDevice, "ParentID")); /**
*
* deviceId,CivilCode;; :
*
* -->
* -->
* -->
* -->
* -->
*
* ,BusinessGroupID;ParentId:
*
* -->
* -->
* -->
* -->
* -->
*/
String parentId = XmlUtil.getText(itemDevice, "ParentID"); String parentId = XmlUtil.getText(itemDevice, "ParentID");
if (parentId != null) { if (parentId != null) {
if (parentId.contains("/")) { if (parentId.contains("/")) {

View File

@ -46,7 +46,7 @@ public interface IMediaServerService {
SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean ssrcCheck); SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean ssrcCheck);
SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean ssrcCheck, boolean isPlayback); SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback);
void closeRTPServer(String deviceId, String channelId, String ssrc); void closeRTPServer(String deviceId, String channelId, String ssrc);

View File

@ -118,11 +118,11 @@ public class MediaServerServiceImpl implements IMediaServerService {
@Override @Override
public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean ssrcCheck) { public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean ssrcCheck) {
return openRTPServer(mediaServerItem, streamId, ssrcCheck,false); return openRTPServer(mediaServerItem, streamId, null, ssrcCheck,false);
} }
@Override @Override
public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean ssrcCheck, boolean isPlayback) { public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String presetSsrc, boolean ssrcCheck, boolean isPlayback) {
if (mediaServerItem == null || mediaServerItem.getId() == null) { if (mediaServerItem == null || mediaServerItem.getId() == null) {
return null; return null;
} }
@ -135,11 +135,15 @@ public class MediaServerServiceImpl implements IMediaServerService {
return null; return null;
}else { }else {
String ssrc = null; String ssrc = null;
if (presetSsrc != null) {
ssrc = presetSsrc;
}else {
if (isPlayback) { if (isPlayback) {
ssrc = ssrcConfig.getPlayBackSsrc(); ssrc = ssrcConfig.getPlayBackSsrc();
}else { }else {
ssrc = ssrcConfig.getPlaySsrc(); ssrc = ssrcConfig.getPlaySsrc();
} }
}
if (streamId == null) { if (streamId == null) {
streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase(); streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();

View File

@ -39,6 +39,7 @@ import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils; import org.springframework.util.ResourceUtils;
import org.springframework.web.context.request.async.DeferredResult; import org.springframework.web.context.request.async.DeferredResult;
import javax.sip.ResponseEvent;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.*; import java.util.*;
@ -256,18 +257,46 @@ public class PlayServiceImpl implements IPlayService {
} }
} }
}, userSetting.getPlayTimeout()); }, userSetting.getPlayTimeout());
final String ssrc = ssrcInfo.getSsrc();
cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> { cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> {
logger.info("收到订阅消息: " + response.toJSONString()); logger.info("收到订阅消息: " + response.toJSONString());
timer.cancel(); timer.cancel();
// hook响应 // hook响应
onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId, uuid); onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId, uuid);
hookEvent.response(mediaServerItemInuse, response); hookEvent.response(mediaServerItemInuse, response);
}, (event) -> {
ResponseEvent responseEvent = (ResponseEvent)event.event;
String contentString = new String(responseEvent.getResponse().getRawContent());
// 获取ssrc
int ssrcIndex = contentString.indexOf("y=");
// 检查是否有y字段
if (ssrcIndex >= 0) {
//ssrc规定长度为10字节不取余下长度以避免后续还有“f=”字段 TODO 后续对不规范的非10位ssrc兼容
String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
if (!ssrc.equals(ssrcInResponse) && device.isSsrcCheck()) { // 查询到ssrc不一致且开启了ssrc校验则需要针对处理
// 查询 ssrcInResponse 是否可用
if (mediaServerItem.isRtpEnable() && !mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) {
// ssrc 不可用
// 释放ssrc
mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc());
streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
event.msg = "下级自定义了ssrc,但是此ssrc不可用";
event.statusCode = 400;
errorEvent.response(event);
return;
}
// 关闭rtp server
mediaServerService.closeRTPServer(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
// 重新开启ssrc server
mediaServerService.openRTPServer(mediaServerItem, finalSsrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), false);
}
}
}, (event) -> { }, (event) -> {
timer.cancel(); timer.cancel();
mediaServerService.closeRTPServer(device.getDeviceId(), channelId, finalSsrcInfo.getStream()); mediaServerService.closeRTPServer(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
// 释放ssrc // 释放ssrc
mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc()); mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc());
streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream()); streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
errorEvent.response(event); errorEvent.response(event);
}); });

View File

@ -93,7 +93,7 @@
<el-button size="mini" icon="el-icon-s-open" type="primary" v-if="scope.row.subCount > 0 || scope.row.parental === 1" <el-button size="mini" icon="el-icon-s-open" type="primary" v-if="scope.row.subCount > 0 || scope.row.parental === 1"
@click="changeSubchannel(scope.row)">查看 @click="changeSubchannel(scope.row)">查看
</el-button> </el-button>
<el-button size="mini" icon="el-icon-video-camera" type="primary" @click="queryRecords(scope.row)"> <el-button size="mini" icon="el-icon-video-camera" type="primary" @click="queryRecords(scope.row)">
</el-button> </el-button>
<!-- <el-button size="mini" @click="sendDevicePush(scope.row)"></el-button> --> <!-- <el-button size="mini" @click="sendDevicePush(scope.row)"></el-button> -->
</el-button-group> </el-button-group>

View File

@ -12,25 +12,22 @@
> >
<div id="shared" style="margin-top: 1rem;margin-right: 100px;"> <div id="shared" style="margin-top: 1rem;margin-right: 100px;">
<el-form ref="form" :rules="rules" :model="form" label-width="140px" > <el-form ref="form" :rules="rules" :model="form" label-width="140px" >
<!-- <el-form-item >-->
<!-- 建议的类型-->
<!-- <br/>-->
<!-- &emsp;&emsp;行政区划可选2位/4/6/8/10位数字例如130432表示河北省邯郸市广平县-->
<!-- <br/>-->
<!-- &emsp;&emsp;业务分组第111213位215例如34020000002150000001-->
<!-- <br/>-->
<!-- &emsp;&emsp;虚拟组织第111213位216例如34020000002160000001-->
<!-- </el-form-item>-->
<el-form-item label="节点编号" prop="id" > <el-form-item label="节点编号" prop="id" >
<el-tooltip class="item" effect="dark" content="" placement="top-start"> <el-input v-model="form.id" :disabled="isEdit" clearable></el-input>
<div slot="content">
建议的类型
<br/>
&emsp;&emsp;行政区划可选2位/4/6/8/10位数字例如130432表示河北省邯郸市广平县
<br/>
&emsp;&emsp;业务分组第111213位215例如34020000002150000001
<br/>
&emsp;&emsp;虚拟组织第111213位216例如34020000002160000001
</div>
<el-input v-model="form.id" :disabled="isEdit"></el-input>
</el-tooltip>
</el-form-item> </el-form-item>
<el-form-item label="节点名称" prop="name"> <el-form-item label="节点名称" prop="name">
<el-input v-model="form.name" clearable></el-input> <el-input v-model="form.name" clearable></el-input>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<div style="float: right;"> <div style="float: right;">
<el-button type="primary" @click="onSubmit" >确认</el-button> <el-button type="primary" @click="onSubmit" >确认</el-button>
@ -65,13 +62,14 @@ export default {
}, },
rules: { rules: {
name: [{ required: true, message: "请输入名称", trigger: "blur" }], name: [{ required: true, message: "请输入名称", trigger: "blur" }],
id: [{ required: true, message: "请输入id", trigger: "blur" }] id: [{ required: true, message: "请输入ID", trigger: "blur" }]
}, },
}; };
}, },
methods: { methods: {
openDialog: function (isEdit, id, name, parentId, callback) { openDialog: function (isEdit, id, name, parentId, callback) {
console.log("parentId: " + parentId) console.log("parentId: " + parentId)
console.log(this.form)
this.isEdit = isEdit; this.isEdit = isEdit;
this.form.id = id; this.form.id = id;
this.form.name = name; this.form.name = name;
@ -105,8 +103,14 @@ export default {
}); });
}, },
close: function () { close: function () {
this.isEdit = false;
this.form.id = null;
this.form.name = null;
this.form.platformId = null;
this.form.parentId = null;
this.callback = null;
this.showDialog = false; this.showDialog = false;
this.$refs.form.resetFields(); console.log(this.form)
}, },
}, },
}; };