Merge branch '648540858:wvp-28181-2.0' into wvp-28181-2.0
This commit is contained in:
commit
7b6e801890
@ -136,4 +136,7 @@ public class SsrcConfig {
|
||||
this.notUsed = notUsed;
|
||||
}
|
||||
|
||||
public boolean checkSsrc(String ssrcInResponse) {
|
||||
return !isUsed.contains(ssrcInResponse);
|
||||
}
|
||||
}
|
||||
|
@ -93,8 +93,8 @@ public interface ISIPCommander {
|
||||
* @param device 视频设备
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* 请求回放视频流
|
||||
*
|
||||
|
@ -343,7 +343,7 @@ public class SIPCommander implements ISIPCommander {
|
||||
*/
|
||||
@Override
|
||||
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();
|
||||
try {
|
||||
if (device == null) return;
|
||||
@ -436,6 +436,7 @@ public class SIPCommander implements ISIPCommander {
|
||||
// 这里为例避免一个通道的点播只有一个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", e.dialog);
|
||||
okEvent.response(e);
|
||||
});
|
||||
|
||||
|
||||
|
@ -202,6 +202,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
|
||||
String platformId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
|
||||
String deviceID = XmlUtil.getText(rootElement, "DeviceID");
|
||||
ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId);
|
||||
if (platform == null)return;
|
||||
SubscribeInfo subscribeInfo = new SubscribeInfo(evt, platformId);
|
||||
if (evt.getServerTransaction() == null) {
|
||||
ServerTransaction serverTransaction = platform.getTransport().equals("TCP") ? tcpSipProvider.getNewServerTransaction(evt.getRequest())
|
||||
|
@ -222,7 +222,24 @@ public class XmlUtil {
|
||||
// 由于海康会错误的发送65535作为这里的取值,所以这里除非是0否则认为是1
|
||||
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");
|
||||
if (parentId != null) {
|
||||
if (parentId.contains("/")) {
|
||||
|
@ -46,7 +46,7 @@ public interface IMediaServerService {
|
||||
|
||||
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);
|
||||
|
||||
|
@ -118,11 +118,11 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
|
||||
@Override
|
||||
public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean ssrcCheck) {
|
||||
return openRTPServer(mediaServerItem, streamId, ssrcCheck,false);
|
||||
return openRTPServer(mediaServerItem, streamId, null, ssrcCheck,false);
|
||||
}
|
||||
|
||||
@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) {
|
||||
return null;
|
||||
}
|
||||
@ -135,10 +135,14 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
return null;
|
||||
}else {
|
||||
String ssrc = null;
|
||||
if (isPlayback) {
|
||||
ssrc = ssrcConfig.getPlayBackSsrc();
|
||||
if (presetSsrc != null) {
|
||||
ssrc = presetSsrc;
|
||||
}else {
|
||||
ssrc = ssrcConfig.getPlaySsrc();
|
||||
if (isPlayback) {
|
||||
ssrc = ssrcConfig.getPlayBackSsrc();
|
||||
}else {
|
||||
ssrc = ssrcConfig.getPlaySsrc();
|
||||
}
|
||||
}
|
||||
|
||||
if (streamId == null) {
|
||||
|
@ -39,6 +39,7 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
|
||||
import javax.sip.ResponseEvent;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
@ -256,18 +257,46 @@ public class PlayServiceImpl implements IPlayService {
|
||||
}
|
||||
}
|
||||
}, userSetting.getPlayTimeout());
|
||||
|
||||
final String ssrc = ssrcInfo.getSsrc();
|
||||
cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> {
|
||||
logger.info("收到订阅消息: " + response.toJSONString());
|
||||
timer.cancel();
|
||||
// hook响应
|
||||
onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId, uuid);
|
||||
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) -> {
|
||||
timer.cancel();
|
||||
mediaServerService.closeRTPServer(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
|
||||
// 释放ssrc
|
||||
mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc());
|
||||
|
||||
streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
|
||||
errorEvent.response(event);
|
||||
});
|
||||
|
@ -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"
|
||||
@click="changeSubchannel(scope.row)">查看
|
||||
</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 size="mini" @click="sendDevicePush(scope.row)">录像查询</el-button> -->
|
||||
</el-button-group>
|
||||
|
@ -12,25 +12,22 @@
|
||||
>
|
||||
<div id="shared" style="margin-top: 1rem;margin-right: 100px;">
|
||||
<el-form ref="form" :rules="rules" :model="form" label-width="140px" >
|
||||
<!-- <el-form-item >-->
|
||||
<!-- 建议的类型:-->
|
||||
<!-- <br/>-->
|
||||
<!--   行政区划(可选2位/4位/6位/8位/10位数字,例如:130432,表示河北省邯郸市广平县)-->
|
||||
<!-- <br/>-->
|
||||
<!--   业务分组(第11、12、13位215,例如:34020000002150000001)-->
|
||||
<!-- <br/>-->
|
||||
<!--   虚拟组织(第11、12、13位216,例如:34020000002160000001)-->
|
||||
<!-- </el-form-item>-->
|
||||
<el-form-item label="节点编号" prop="id" >
|
||||
<el-tooltip class="item" effect="dark" content="" placement="top-start">
|
||||
<div slot="content">
|
||||
建议的类型:
|
||||
<br/>
|
||||
  行政区划(可选2位/4位/6位/8位/10位数字,例如:130432,表示河北省邯郸市广平县)
|
||||
<br/>
|
||||
  业务分组(第11、12、13位215,例如:34020000002150000001)
|
||||
<br/>
|
||||
  虚拟组织(第11、12、13位216,例如:34020000002160000001)
|
||||
</div>
|
||||
<el-input v-model="form.id" :disabled="isEdit"></el-input>
|
||||
</el-tooltip>
|
||||
<el-input v-model="form.id" :disabled="isEdit" clearable></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="节点名称" prop="name">
|
||||
<el-input v-model="form.name" clearable></el-input>
|
||||
</el-form-item>
|
||||
|
||||
|
||||
<el-form-item>
|
||||
<div style="float: right;">
|
||||
<el-button type="primary" @click="onSubmit" >确认</el-button>
|
||||
@ -65,13 +62,14 @@ export default {
|
||||
},
|
||||
rules: {
|
||||
name: [{ required: true, message: "请输入名称", trigger: "blur" }],
|
||||
id: [{ required: true, message: "请输入id", trigger: "blur" }]
|
||||
id: [{ required: true, message: "请输入ID", trigger: "blur" }]
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
openDialog: function (isEdit, id, name, parentId, callback) {
|
||||
console.log("parentId: " + parentId)
|
||||
console.log(this.form)
|
||||
this.isEdit = isEdit;
|
||||
this.form.id = id;
|
||||
this.form.name = name;
|
||||
@ -105,8 +103,14 @@ export default {
|
||||
});
|
||||
},
|
||||
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.$refs.form.resetFields();
|
||||
console.log(this.form)
|
||||
},
|
||||
},
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user