Merge remote-tracking branch 'origin/1078' into 1078
This commit is contained in:
@@ -178,6 +178,10 @@ public class VideoManagerConstants {
|
||||
//************************** 1078 ****************************************
|
||||
|
||||
|
||||
public static final String INVITE_INFO_1078 = "INVITE_INFO_1078:";
|
||||
public static final String INVITE_INFO_1078_PLAY = "INVITE_INFO_1078_PLAY:";
|
||||
public static final String INVITE_INFO_1078_PLAYBACK = "INVITE_INFO_1078_PLAYBACK:";
|
||||
|
||||
|
||||
public static final String RECORD_LIST_1078 = "RECORD_LIST_1078:";
|
||||
|
||||
}
|
||||
|
||||
@@ -22,6 +22,14 @@ public class JT1078Template {
|
||||
private static final String H9201 = "9201";
|
||||
private static final String H9202 = "9202";
|
||||
private static final String H9205 = "9205";
|
||||
private static final String H9206 = "9206";
|
||||
private static final String H9207 = "9207";
|
||||
private static final String H9301 = "9301";
|
||||
private static final String H9302 = "9302";
|
||||
private static final String H9303 = "9303";
|
||||
private static final String H9304 = "9304";
|
||||
private static final String H9305 = "9305";
|
||||
private static final String H9306 = "9306";
|
||||
|
||||
private static final String H0001 = "0001";
|
||||
private static final String H1205 = "1205";
|
||||
@@ -111,6 +119,142 @@ public class JT1078Template {
|
||||
return SessionManager.INSTANCE.request(cmd, timeOut);
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件上传
|
||||
*
|
||||
* @param devId 设备号
|
||||
* @param j9206 文件上传参数
|
||||
*/
|
||||
public String fileUpload(String devId, J9206 j9206, Integer timeOut) {
|
||||
Cmd cmd = new Cmd.Builder()
|
||||
.setDevId(devId)
|
||||
.setPackageNo(randomInt())
|
||||
.setMsgId(H9206)
|
||||
.setRespId(H0001)
|
||||
.setRs(j9206)
|
||||
.build();
|
||||
return SessionManager.INSTANCE.request(cmd, timeOut);
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件上传控制
|
||||
*
|
||||
* @param devId 设备号
|
||||
* @param j9207 文件上传控制参数
|
||||
*/
|
||||
public String fileUploadControl(String devId, J9207 j9207, Integer timeOut) {
|
||||
Cmd cmd = new Cmd.Builder()
|
||||
.setDevId(devId)
|
||||
.setPackageNo(randomInt())
|
||||
.setMsgId(H9207)
|
||||
.setRespId(H0001)
|
||||
.setRs(j9207)
|
||||
.build();
|
||||
return SessionManager.INSTANCE.request(cmd, timeOut);
|
||||
}
|
||||
|
||||
/**
|
||||
* 云台控制指令-云台旋转
|
||||
*
|
||||
* @param devId 设备号
|
||||
* @param j9301 云台旋转参数
|
||||
*/
|
||||
public String ptzRotate(String devId, J9301 j9301, Integer timeOut) {
|
||||
Cmd cmd = new Cmd.Builder()
|
||||
.setDevId(devId)
|
||||
.setPackageNo(randomInt())
|
||||
.setMsgId(H9301)
|
||||
.setRespId(H0001)
|
||||
.setRs(j9301)
|
||||
.build();
|
||||
return SessionManager.INSTANCE.request(cmd, timeOut);
|
||||
}
|
||||
|
||||
/**
|
||||
* 云台控制指令-云台调整焦距控制
|
||||
*
|
||||
* @param devId 设备号
|
||||
* @param j9302 云台焦距控制参数
|
||||
*/
|
||||
public String ptzFocal(String devId, J9302 j9302, Integer timeOut) {
|
||||
Cmd cmd = new Cmd.Builder()
|
||||
.setDevId(devId)
|
||||
.setPackageNo(randomInt())
|
||||
.setMsgId(H9302)
|
||||
.setRespId(H0001)
|
||||
.setRs(j9302)
|
||||
.build();
|
||||
return SessionManager.INSTANCE.request(cmd, timeOut);
|
||||
}
|
||||
|
||||
/**
|
||||
* 云台控制指令-云台调整光圈控制
|
||||
*
|
||||
* @param devId 设备号
|
||||
* @param j9303 云台光圈控制参数
|
||||
*/
|
||||
public String ptzIris(String devId, J9303 j9303, Integer timeOut) {
|
||||
Cmd cmd = new Cmd.Builder()
|
||||
.setDevId(devId)
|
||||
.setPackageNo(randomInt())
|
||||
.setMsgId(H9303)
|
||||
.setRespId(H0001)
|
||||
.setRs(j9303)
|
||||
.build();
|
||||
return SessionManager.INSTANCE.request(cmd, timeOut);
|
||||
}
|
||||
|
||||
/**
|
||||
* 云台控制指令-云台雨刷控制
|
||||
*
|
||||
* @param devId 设备号
|
||||
* @param j9304 云台雨刷控制参数
|
||||
*/
|
||||
public String ptzWiper(String devId, J9304 j9304, Integer timeOut) {
|
||||
Cmd cmd = new Cmd.Builder()
|
||||
.setDevId(devId)
|
||||
.setPackageNo(randomInt())
|
||||
.setMsgId(H9304)
|
||||
.setRespId(H0001)
|
||||
.setRs(j9304)
|
||||
.build();
|
||||
return SessionManager.INSTANCE.request(cmd, timeOut);
|
||||
}
|
||||
|
||||
/**
|
||||
* 云台控制指令-红外补光控制
|
||||
*
|
||||
* @param devId 设备号
|
||||
* @param j9305 云台红外补光控制参数
|
||||
*/
|
||||
public String ptzSupplementaryLight(String devId, J9305 j9305, Integer timeOut) {
|
||||
Cmd cmd = new Cmd.Builder()
|
||||
.setDevId(devId)
|
||||
.setPackageNo(randomInt())
|
||||
.setMsgId(H9305)
|
||||
.setRespId(H0001)
|
||||
.setRs(j9305)
|
||||
.build();
|
||||
return SessionManager.INSTANCE.request(cmd, timeOut);
|
||||
}
|
||||
|
||||
/**
|
||||
* 云台控制指令-变倍控制
|
||||
*
|
||||
* @param devId 设备号
|
||||
* @param j9306 云台变倍控制参数
|
||||
*/
|
||||
public String ptzZoom(String devId, J9306 j9306, Integer timeOut) {
|
||||
Cmd cmd = new Cmd.Builder()
|
||||
.setDevId(devId)
|
||||
.setPackageNo(randomInt())
|
||||
.setMsgId(H9306)
|
||||
.setRespId(H0001)
|
||||
.setRs(j9306)
|
||||
.build();
|
||||
return SessionManager.INSTANCE.request(cmd, timeOut);
|
||||
}
|
||||
|
||||
private Long randomInt() {
|
||||
return (long) random.nextInt(1000) + 1;
|
||||
}
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
package com.genersoft.iot.vmp.jt1078.config;
|
||||
|
||||
import com.genersoft.iot.vmp.common.InviteSessionType;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.conf.security.JwtUtils;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.jt1078.bean.JTDevice;
|
||||
import com.genersoft.iot.vmp.jt1078.cmd.JT1078Template;
|
||||
import com.genersoft.iot.vmp.jt1078.proc.response.*;
|
||||
import com.genersoft.iot.vmp.jt1078.proc.request.J1205;
|
||||
import com.genersoft.iot.vmp.jt1078.service.Ijt1078Service;
|
||||
import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.StreamContent;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
|
||||
import com.genersoft.iot.vmp.vmanager.gb28181.play.PlayController;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
@@ -120,6 +115,126 @@ public class JT1078Controller {
|
||||
service.stopPlay(deviceId, channelId);
|
||||
}
|
||||
|
||||
@Operation(summary = "1078-暂停点播", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号, 一般为从1开始的数字", required = true)
|
||||
@GetMapping("/live/pause")
|
||||
public void pauseLive(HttpServletRequest request,
|
||||
@Parameter(required = true) String deviceId,
|
||||
@Parameter(required = false) String channelId) {
|
||||
if (ObjectUtils.isEmpty(channelId)) {
|
||||
channelId = "1";
|
||||
}
|
||||
service.pausePlay(deviceId, channelId);
|
||||
}
|
||||
|
||||
@Operation(summary = "1078-继续点播", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号, 一般为从1开始的数字", required = true)
|
||||
@GetMapping("/live/continue")
|
||||
public void continueLive(HttpServletRequest request,
|
||||
@Parameter(required = true) String deviceId,
|
||||
@Parameter(required = false) String channelId) {
|
||||
if (ObjectUtils.isEmpty(channelId)) {
|
||||
channelId = "1";
|
||||
}
|
||||
service.continueLivePlay(deviceId, channelId);
|
||||
}
|
||||
|
||||
@Operation(summary = "1078-录像-查询资源列表", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号, 一般为从1开始的数字", required = true)
|
||||
@Parameter(name = "startTime", description = "开始时间,格式: yyyy-MM-dd HH:mm:ss", required = true)
|
||||
@Parameter(name = "endTime", description = "结束时间,格式: yyyy-MM-dd HH:mm:ss", required = true)
|
||||
@GetMapping("/record/list")
|
||||
public WVPResult<List<J1205.JRecordItem>> playbackList(HttpServletRequest request,
|
||||
@Parameter(required = true) String deviceId,
|
||||
@Parameter(required = false) String channelId,
|
||||
@Parameter(required = true) String startTime,
|
||||
@Parameter(required = true) String endTime
|
||||
) {
|
||||
if (ObjectUtils.isEmpty(channelId)) {
|
||||
channelId = "1";
|
||||
}
|
||||
List<J1205.JRecordItem> recordList = service.getRecordList(deviceId, channelId, startTime, endTime);
|
||||
if (recordList == null) {
|
||||
return WVPResult.fail(ErrorCode.ERROR100);
|
||||
}else {
|
||||
return WVPResult.success(recordList);
|
||||
}
|
||||
}
|
||||
@Operation(summary = "1078-开始回放", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号, 一般为从1开始的数字", required = true)
|
||||
@Parameter(name = "startTime", description = "开始时间,格式: yyyy-MM-dd HH:mm:ss", required = true)
|
||||
@Parameter(name = "endTime", description = "结束时间,格式: yyyy-MM-dd HH:mm:ss", required = true)
|
||||
@GetMapping("/playback/start")
|
||||
public DeferredResult<WVPResult<StreamContent>> recordLive(HttpServletRequest request,
|
||||
@Parameter(required = true) String deviceId,
|
||||
@Parameter(required = false) String channelId,
|
||||
@Parameter(required = true) String startTime,
|
||||
@Parameter(required = true) String endTime) {
|
||||
DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue());
|
||||
if (ObjectUtils.isEmpty(channelId)) {
|
||||
channelId = "1";
|
||||
}
|
||||
String finalChannelId = channelId;
|
||||
result.onTimeout(()->{
|
||||
logger.info("[1078-回放-等待超时] deviceId:{}, channelId:{}, ", deviceId, finalChannelId);
|
||||
// 释放rtpserver
|
||||
WVPResult<StreamContent> wvpResult = new WVPResult<>();
|
||||
wvpResult.setCode(ErrorCode.ERROR100.getCode());
|
||||
wvpResult.setMsg("回放超时");
|
||||
result.setResult(wvpResult);
|
||||
service.stopPlay(deviceId, finalChannelId);
|
||||
});
|
||||
|
||||
service.playback(deviceId, channelId, startTime, endTime, (code, msg, streamInfo) -> {
|
||||
WVPResult<StreamContent> wvpResult = new WVPResult<>();
|
||||
if (code == InviteErrorCode.SUCCESS.getCode()) {
|
||||
wvpResult.setCode(ErrorCode.SUCCESS.getCode());
|
||||
wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());
|
||||
|
||||
if (streamInfo != null) {
|
||||
if (userSetting.getUseSourceIpAsStreamIp()) {
|
||||
streamInfo=streamInfo.clone();//深拷贝
|
||||
String host;
|
||||
try {
|
||||
URL url=new URL(request.getRequestURL().toString());
|
||||
host=url.getHost();
|
||||
} catch (MalformedURLException e) {
|
||||
host=request.getLocalAddr();
|
||||
}
|
||||
streamInfo.channgeStreamIp(host);
|
||||
}
|
||||
wvpResult.setData(new StreamContent(streamInfo));
|
||||
}else {
|
||||
wvpResult.setCode(code);
|
||||
wvpResult.setMsg(msg);
|
||||
}
|
||||
}else {
|
||||
wvpResult.setCode(code);
|
||||
wvpResult.setMsg(msg);
|
||||
}
|
||||
result.setResult(wvpResult);
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Operation(summary = "1078-结束回放", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号, 一般为从1开始的数字", required = true)
|
||||
@GetMapping("/playback/stop")
|
||||
public void stopPlayback(HttpServletRequest request,
|
||||
@Parameter(required = true) String deviceId,
|
||||
@Parameter(required = false) String channelId) {
|
||||
if (ObjectUtils.isEmpty(channelId)) {
|
||||
channelId = "1";
|
||||
}
|
||||
service.stopPlayback(deviceId, channelId);
|
||||
}
|
||||
|
||||
@Operation(summary = "分页查询部标设备", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "page", description = "当前页", required = true)
|
||||
@Parameter(name = "count", description = "每页查询数量", required = true)
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.genersoft.iot.vmp.jt1078.event;
|
||||
|
||||
import com.genersoft.iot.vmp.common.GeneralCallback;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 管理callback回调,支持设置超时时间,未设置则按照五分钟超时自动移除
|
||||
*/
|
||||
@Component
|
||||
public class CallbackManager {
|
||||
|
||||
private final long expire = 5 * 60 * 1000;
|
||||
|
||||
static class ManagerCallBack {
|
||||
public String key;
|
||||
public GeneralCallback<?> callback;
|
||||
public long createTime;
|
||||
public long expire;
|
||||
}
|
||||
|
||||
private final Map<String, ManagerCallBack> allCallbacks = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
public void addCallback(String key, GeneralCallback<?> callback) {
|
||||
ManagerCallBack managerCallBack = new ManagerCallBack();
|
||||
managerCallBack.callback = callback;
|
||||
managerCallBack.key = key;
|
||||
managerCallBack.createTime = System.currentTimeMillis();
|
||||
managerCallBack.expire = expire;
|
||||
allCallbacks.put(key, managerCallBack);
|
||||
}
|
||||
|
||||
public void addCallback(String key, GeneralCallback<Object> callback, long timeout) {
|
||||
ManagerCallBack managerCallBack = new ManagerCallBack();
|
||||
managerCallBack.callback = callback;
|
||||
managerCallBack.key = key;
|
||||
managerCallBack.createTime = System.currentTimeMillis();
|
||||
managerCallBack.expire = timeout;
|
||||
allCallbacks.put(key, managerCallBack);
|
||||
}
|
||||
|
||||
public GeneralCallback<?> getCallback(String key){
|
||||
ManagerCallBack managerCallBack = allCallbacks.get(key);
|
||||
if (managerCallBack != null) {
|
||||
return managerCallBack.callback;
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void removeCallback(String key){
|
||||
allCallbacks.remove(key);
|
||||
}
|
||||
/**
|
||||
* 对订阅数据进行过期清理
|
||||
*/
|
||||
@Scheduled(fixedRate=expire) //每5分钟执行一次
|
||||
public void execute(){
|
||||
for (ManagerCallBack callBack : allCallbacks.values()) {
|
||||
if ((System.currentTimeMillis() - callBack.createTime - callBack.expire) > 0) {
|
||||
allCallbacks.remove(callBack.key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,14 +45,13 @@ public class J1205 extends Re {
|
||||
item.setSize(buf.readUnsignedInt());
|
||||
recordList.add(item);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Rs handler(Header header, Session session, Ijt1078Service service) {
|
||||
// TODO 可能未处理分包的情况
|
||||
SessionManager.INSTANCE.response(header.getTerminalId(), "1205", (long) respNo, JSON.toJSONString(this));
|
||||
|
||||
J8001 j8001 = new J8001();
|
||||
j8001.setRespNo(header.getSn());
|
||||
j8001.setRespId(header.getMsgId());
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.genersoft.iot.vmp.jt1078.proc.request;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.genersoft.iot.vmp.jt1078.annotation.MsgId;
|
||||
import com.genersoft.iot.vmp.jt1078.proc.Header;
|
||||
import com.genersoft.iot.vmp.jt1078.proc.response.J8001;
|
||||
import com.genersoft.iot.vmp.jt1078.proc.response.Rs;
|
||||
import com.genersoft.iot.vmp.jt1078.service.Ijt1078Service;
|
||||
import com.genersoft.iot.vmp.jt1078.session.Session;
|
||||
import com.genersoft.iot.vmp.jt1078.session.SessionManager;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufUtil;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 文件上传完成通知
|
||||
*
|
||||
*/
|
||||
@MsgId(id = "1206")
|
||||
public class J1206 extends Re {
|
||||
Integer respNo;
|
||||
|
||||
// 0:成功; 1:失败
|
||||
private int result;
|
||||
|
||||
@Override
|
||||
protected Rs decode0(ByteBuf buf, Header header, Session session) {
|
||||
respNo = buf.readUnsignedShort();
|
||||
result = buf.readUnsignedByte();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Rs handler(Header header, Session session, Ijt1078Service service) {
|
||||
J8001 j8001 = new J8001();
|
||||
j8001.setRespNo(header.getSn());
|
||||
j8001.setRespId(header.getMsgId());
|
||||
j8001.setResult(J8001.SUCCESS);
|
||||
return j8001;
|
||||
}
|
||||
|
||||
|
||||
public Integer getRespNo() {
|
||||
return respNo;
|
||||
}
|
||||
|
||||
public void setRespNo(Integer respNo) {
|
||||
this.respNo = respNo;
|
||||
}
|
||||
|
||||
public int getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setResult(int result) {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "J1206{" +
|
||||
"respNo=" + respNo +
|
||||
", result=" + result +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApplicationEvent getEvent() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
package com.genersoft.iot.vmp.jt1078.proc.response;
|
||||
|
||||
import com.genersoft.iot.vmp.jt1078.annotation.MsgId;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufUtil;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.util.CharsetUtil;
|
||||
|
||||
/**
|
||||
* 文件上传指令
|
||||
*
|
||||
*/
|
||||
@MsgId(id = "9206")
|
||||
public class J9206 extends Rs {
|
||||
|
||||
// 服务器地址
|
||||
private String serverIp;
|
||||
// 服务器端口
|
||||
private int port;
|
||||
// 用户名
|
||||
private String user;
|
||||
// 密码
|
||||
private String password;
|
||||
// 文件上传路径
|
||||
private String path;
|
||||
// 逻辑通道号
|
||||
private int channelId;
|
||||
|
||||
// 开始时间YYMMDDHHMMSS,全0表示无起始时间
|
||||
private String startTime;
|
||||
|
||||
// 结束时间YYMMDDHHMMSS,全0表示无终止时间
|
||||
private String endTime;
|
||||
|
||||
// 报警标志
|
||||
private final int warnType = 0;
|
||||
|
||||
// 音视频资源类型:0.音视频 1.音频 2.视频 3.视频或音视频
|
||||
private int mediaType;
|
||||
|
||||
// 码流类型:0.所有码流 1.主码流 2.子码流
|
||||
private int streamType = 0;
|
||||
|
||||
// 存储器类型:0.所有存储器 1.主存储器 2.灾备存储器
|
||||
private int storageType = 0;
|
||||
|
||||
// 任务执行条件,
|
||||
// 1:仅WI-FI 下可下载,
|
||||
// 2: 仅LAN 连接时可下载;
|
||||
// 3: WI-FI + LAN 连接时可下载;
|
||||
// 4: 仅3G/ 4G 连接时可下载
|
||||
// 5: WI-FI + 3G/ 4G 连接时可下载
|
||||
// 6: WI-FI + LAN 连接时可下载
|
||||
// 7: WI-FI + LAN + 3G/ 4G 连接时可下载
|
||||
private int taskConditions = 7;
|
||||
|
||||
@Override
|
||||
public ByteBuf encode() {
|
||||
ByteBuf buffer = Unpooled.buffer();
|
||||
|
||||
buffer.writeByte(serverIp.getBytes().length);
|
||||
buffer.writeCharSequence(serverIp, CharsetUtil.UTF_8);
|
||||
buffer.writeByte(port);
|
||||
buffer.writeByte(user.getBytes().length);
|
||||
buffer.writeCharSequence(user, CharsetUtil.UTF_8);
|
||||
buffer.writeByte(password.getBytes().length);
|
||||
buffer.writeCharSequence(password, CharsetUtil.UTF_8);
|
||||
buffer.writeByte(path.getBytes().length);
|
||||
buffer.writeCharSequence(path, CharsetUtil.UTF_8);
|
||||
buffer.writeByte(channelId);
|
||||
buffer.writeBytes(ByteBufUtil.decodeHexDump(startTime));
|
||||
buffer.writeBytes(ByteBufUtil.decodeHexDump(endTime));
|
||||
buffer.writeLong(warnType);
|
||||
buffer.writeByte(mediaType);
|
||||
buffer.writeByte(streamType);
|
||||
buffer.writeByte(storageType);
|
||||
buffer.writeByte(taskConditions);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
public String getServerIp() {
|
||||
return serverIp;
|
||||
}
|
||||
|
||||
public void setServerIp(String serverIp) {
|
||||
this.serverIp = serverIp;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public String getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(String user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public int getChannelId() {
|
||||
return channelId;
|
||||
}
|
||||
|
||||
public void setChannelId(int channelId) {
|
||||
this.channelId = channelId;
|
||||
}
|
||||
|
||||
public String getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public void setStartTime(String startTime) {
|
||||
this.startTime = startTime;
|
||||
}
|
||||
|
||||
public String getEndTime() {
|
||||
return endTime;
|
||||
}
|
||||
|
||||
public void setEndTime(String endTime) {
|
||||
this.endTime = endTime;
|
||||
}
|
||||
|
||||
public int getWarnType() {
|
||||
return warnType;
|
||||
}
|
||||
|
||||
public int getMediaType() {
|
||||
return mediaType;
|
||||
}
|
||||
|
||||
public void setMediaType(int mediaType) {
|
||||
this.mediaType = mediaType;
|
||||
}
|
||||
|
||||
public int getStreamType() {
|
||||
return streamType;
|
||||
}
|
||||
|
||||
public void setStreamType(int streamType) {
|
||||
this.streamType = streamType;
|
||||
}
|
||||
|
||||
public int getStorageType() {
|
||||
return storageType;
|
||||
}
|
||||
|
||||
public void setStorageType(int storageType) {
|
||||
this.storageType = storageType;
|
||||
}
|
||||
|
||||
public int getTaskConditions() {
|
||||
return taskConditions;
|
||||
}
|
||||
|
||||
public void setTaskConditions(int taskConditions) {
|
||||
this.taskConditions = taskConditions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "J9206{" +
|
||||
"serverIp='" + serverIp + '\'' +
|
||||
", port=" + port +
|
||||
", user='" + user + '\'' +
|
||||
", password='" + password + '\'' +
|
||||
", path='" + path + '\'' +
|
||||
", channelId=" + channelId +
|
||||
", startTime='" + startTime + '\'' +
|
||||
", endTime='" + endTime + '\'' +
|
||||
", warnType=" + warnType +
|
||||
", mediaType=" + mediaType +
|
||||
", streamType=" + streamType +
|
||||
", storageType=" + storageType +
|
||||
", taskConditions=" + taskConditions +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.genersoft.iot.vmp.jt1078.proc.response;
|
||||
|
||||
import com.genersoft.iot.vmp.jt1078.annotation.MsgId;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufUtil;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.util.CharsetUtil;
|
||||
|
||||
/**
|
||||
* 文件上传控制
|
||||
*
|
||||
*/
|
||||
@MsgId(id = "9207")
|
||||
public class J9207 extends Rs {
|
||||
|
||||
// 对应平台文件上传消息的流水号
|
||||
Integer respNo;
|
||||
|
||||
// 控制: 0:暂停; 1:继续; 2:取消
|
||||
private int control;
|
||||
|
||||
@Override
|
||||
public ByteBuf encode() {
|
||||
ByteBuf buffer = Unpooled.buffer();
|
||||
buffer.writeShort(respNo);
|
||||
buffer.writeByte(control);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
public Integer getRespNo() {
|
||||
return respNo;
|
||||
}
|
||||
|
||||
public void setRespNo(Integer respNo) {
|
||||
this.respNo = respNo;
|
||||
}
|
||||
|
||||
public int getControl() {
|
||||
return control;
|
||||
}
|
||||
|
||||
public void setControl(int control) {
|
||||
this.control = control;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "J9207{" +
|
||||
"respNo=" + respNo +
|
||||
", control=" + control +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.genersoft.iot.vmp.jt1078.proc.response;
|
||||
|
||||
import com.genersoft.iot.vmp.jt1078.annotation.MsgId;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufUtil;
|
||||
import io.netty.buffer.Unpooled;
|
||||
|
||||
/**
|
||||
* 云台控制指令-云台旋转
|
||||
*
|
||||
*/
|
||||
@MsgId(id = "9301")
|
||||
public class J9301 extends Rs {
|
||||
// 逻辑通道号
|
||||
private int channel;
|
||||
|
||||
// 方向: 0:停止; 1:上; 2:下; 3:左; 4:右
|
||||
private int direction;
|
||||
|
||||
// 速度:0 ~ 255
|
||||
private int speed;
|
||||
|
||||
@Override
|
||||
public ByteBuf encode() {
|
||||
ByteBuf buffer = Unpooled.buffer();
|
||||
buffer.writeByte(channel);
|
||||
buffer.writeByte(direction);
|
||||
buffer.writeByte(speed);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public int getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public void setChannel(int channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
public int getDirection() {
|
||||
return direction;
|
||||
}
|
||||
|
||||
public void setDirection(int direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
public int getSpeed() {
|
||||
return speed;
|
||||
}
|
||||
|
||||
public void setSpeed(int speed) {
|
||||
this.speed = speed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "J9301{" +
|
||||
"channel=" + channel +
|
||||
", direction=" + direction +
|
||||
", speed=" + speed +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.genersoft.iot.vmp.jt1078.proc.response;
|
||||
|
||||
import com.genersoft.iot.vmp.jt1078.annotation.MsgId;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
|
||||
/**
|
||||
* 云台控制指令-焦距控制
|
||||
*
|
||||
*/
|
||||
@MsgId(id = "9302")
|
||||
public class J9302 extends Rs {
|
||||
// 逻辑通道号
|
||||
private int channel;
|
||||
|
||||
// 方向: 0:焦距调大; 1:焦距调小
|
||||
private int focalDirection;
|
||||
|
||||
@Override
|
||||
public ByteBuf encode() {
|
||||
ByteBuf buffer = Unpooled.buffer();
|
||||
buffer.writeByte(channel);
|
||||
buffer.writeByte(focalDirection);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public int getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public void setChannel(int channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
public int getFocalDirection() {
|
||||
return focalDirection;
|
||||
}
|
||||
|
||||
public void setFocalDirection(int focalDirection) {
|
||||
this.focalDirection = focalDirection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "J9302{" +
|
||||
"channel=" + channel +
|
||||
", zoomDirection=" + focalDirection +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.genersoft.iot.vmp.jt1078.proc.response;
|
||||
|
||||
import com.genersoft.iot.vmp.jt1078.annotation.MsgId;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
|
||||
/**
|
||||
* 云台控制指令-光圈控制
|
||||
*
|
||||
*/
|
||||
@MsgId(id = "9303")
|
||||
public class J9303 extends Rs {
|
||||
// 逻辑通道号
|
||||
private int channel;
|
||||
|
||||
// 调整方式: 0:调大; 1:调小
|
||||
private int iris;
|
||||
|
||||
@Override
|
||||
public ByteBuf encode() {
|
||||
ByteBuf buffer = Unpooled.buffer();
|
||||
buffer.writeByte(channel);
|
||||
buffer.writeByte(iris);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public int getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public void setChannel(int channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
public int getIris() {
|
||||
return iris;
|
||||
}
|
||||
|
||||
public void setIris(int iris) {
|
||||
this.iris = iris;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "J9303{" +
|
||||
"channel=" + channel +
|
||||
", iris=" + iris +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.genersoft.iot.vmp.jt1078.proc.response;
|
||||
|
||||
import com.genersoft.iot.vmp.jt1078.annotation.MsgId;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
|
||||
/**
|
||||
* 云台控制指令-云台雨刷控制
|
||||
*
|
||||
*/
|
||||
@MsgId(id = "9304")
|
||||
public class J9304 extends Rs {
|
||||
// 逻辑通道号
|
||||
private int channel;
|
||||
|
||||
// 启停标识: 0:停止; 1:启动
|
||||
private int on;
|
||||
|
||||
@Override
|
||||
public ByteBuf encode() {
|
||||
ByteBuf buffer = Unpooled.buffer();
|
||||
buffer.writeByte(channel);
|
||||
buffer.writeByte(on);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public int getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public void setChannel(int channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
public int getOn() {
|
||||
return on;
|
||||
}
|
||||
|
||||
public void setOn(int on) {
|
||||
this.on = on;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "J9304{" +
|
||||
"channel=" + channel +
|
||||
", on=" + on +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.genersoft.iot.vmp.jt1078.proc.response;
|
||||
|
||||
import com.genersoft.iot.vmp.jt1078.annotation.MsgId;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
|
||||
/**
|
||||
* 云台控制指令-红外补光控制
|
||||
*
|
||||
*/
|
||||
@MsgId(id = "9305")
|
||||
public class J9305 extends Rs {
|
||||
// 逻辑通道号
|
||||
private int channel;
|
||||
|
||||
// 启停标识: 0:停止; 1:启动
|
||||
private int on;
|
||||
|
||||
@Override
|
||||
public ByteBuf encode() {
|
||||
ByteBuf buffer = Unpooled.buffer();
|
||||
buffer.writeByte(channel);
|
||||
buffer.writeByte(on);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public int getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public void setChannel(int channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
public int getOn() {
|
||||
return on;
|
||||
}
|
||||
|
||||
public void setOn(int on) {
|
||||
this.on = on;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "J9305{" +
|
||||
"channel=" + channel +
|
||||
", on=" + on +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.genersoft.iot.vmp.jt1078.proc.response;
|
||||
|
||||
import com.genersoft.iot.vmp.jt1078.annotation.MsgId;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
|
||||
/**
|
||||
* 云台控制指令-云台变倍控制
|
||||
*
|
||||
*/
|
||||
@MsgId(id = "9306")
|
||||
public class J9306 extends Rs {
|
||||
// 逻辑通道号
|
||||
private int channel;
|
||||
|
||||
// 0:调大; 1:调小
|
||||
private int zoom;
|
||||
|
||||
@Override
|
||||
public ByteBuf encode() {
|
||||
ByteBuf buffer = Unpooled.buffer();
|
||||
buffer.writeByte(channel);
|
||||
buffer.writeByte(zoom);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public int getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public void setChannel(int channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
public int getZoom() {
|
||||
return zoom;
|
||||
}
|
||||
|
||||
public void setZoom(int zoom) {
|
||||
this.zoom = zoom;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "J9306{" +
|
||||
"channel=" + channel +
|
||||
", zoom=" + zoom +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.genersoft.iot.vmp.jt1078.service;
|
||||
|
||||
import com.genersoft.iot.vmp.common.CommonCallback;
|
||||
import com.genersoft.iot.vmp.common.GeneralCallback;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.jt1078.bean.JTDevice;
|
||||
import com.genersoft.iot.vmp.jt1078.proc.request.J1205;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
|
||||
import java.util.List;
|
||||
@@ -23,5 +23,15 @@ public interface Ijt1078Service {
|
||||
|
||||
void play(String deviceId, String channelId, GeneralCallback<StreamInfo> callback);
|
||||
|
||||
void playback(String deviceId, String channelId, String startTime, String endTime, GeneralCallback<StreamInfo> callback);
|
||||
|
||||
void stopPlay(String deviceId, String channelId);
|
||||
|
||||
void pausePlay(String deviceId, String channelId);
|
||||
|
||||
void continueLivePlay(String deviceId, String channelId);
|
||||
|
||||
List<J1205.JRecordItem> getRecordList(String deviceId, String channelId, String startTime, String endTime);
|
||||
|
||||
void stopPlayback(String deviceId, String channelId);
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
package com.genersoft.iot.vmp.jt1078.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.genersoft.iot.vmp.common.GeneralCallback;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||
import com.genersoft.iot.vmp.conf.DynamicTask;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
|
||||
import com.genersoft.iot.vmp.jt1078.bean.JTDevice;
|
||||
import com.genersoft.iot.vmp.jt1078.cmd.JT1078Template;
|
||||
import com.genersoft.iot.vmp.jt1078.config.JT1078Controller;
|
||||
import com.genersoft.iot.vmp.jt1078.dao.JTDeviceMapper;
|
||||
import com.genersoft.iot.vmp.jt1078.proc.response.J9101;
|
||||
import com.genersoft.iot.vmp.jt1078.proc.response.J9102;
|
||||
import com.genersoft.iot.vmp.jt1078.event.CallbackManager;
|
||||
import com.genersoft.iot.vmp.jt1078.proc.request.J1205;
|
||||
import com.genersoft.iot.vmp.jt1078.proc.response.*;
|
||||
import com.genersoft.iot.vmp.jt1078.service.Ijt1078Service;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
|
||||
@@ -23,24 +23,17 @@ import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
|
||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.service.IMediaService;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
|
||||
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -78,6 +71,9 @@ public class jt1078ServiceImpl implements Ijt1078Service {
|
||||
@Autowired
|
||||
private ZLMRESTfulUtils zlmresTfulUtils;
|
||||
|
||||
@Autowired
|
||||
private CallbackManager callbackManager;
|
||||
|
||||
|
||||
@Override
|
||||
public JTDevice getDevice(String terminalId) {
|
||||
@@ -120,7 +116,7 @@ public class jt1078ServiceImpl implements Ijt1078Service {
|
||||
public void play(String deviceId, String channelId, GeneralCallback<StreamInfo> callback) {
|
||||
|
||||
// 检查流是否已经存在,存在则返回
|
||||
String playKey = VideoManagerConstants.INVITE_INFO_1078 + deviceId + ":" + channelId;
|
||||
String playKey = VideoManagerConstants.INVITE_INFO_1078_PLAY + deviceId + ":" + channelId;
|
||||
List<GeneralCallback<StreamInfo>> errorCallbacks = inviteErrorCallbackMap.computeIfAbsent(playKey, k -> new ArrayList<>());
|
||||
errorCallbacks.add(callback);
|
||||
StreamInfo streamInfo = (StreamInfo)redisTemplate.opsForValue().get(playKey);
|
||||
@@ -146,7 +142,12 @@ public class jt1078ServiceImpl implements Ijt1078Service {
|
||||
}
|
||||
String stream = deviceId + "-" + channelId;
|
||||
MediaServerItem mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(null);
|
||||
|
||||
if (mediaServerItem == null) {
|
||||
for (GeneralCallback<StreamInfo> errorCallback : errorCallbacks) {
|
||||
errorCallback.run(InviteErrorCode.FAIL.getCode(), "未找到可用的媒体节点", streamInfo);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// 设置hook监听
|
||||
HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId());
|
||||
subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, HookParam hookParam) -> {
|
||||
@@ -195,7 +196,7 @@ public class jt1078ServiceImpl implements Ijt1078Service {
|
||||
|
||||
@Override
|
||||
public void stopPlay(String deviceId, String channelId) {
|
||||
String playKey = VideoManagerConstants.INVITE_INFO_1078 + deviceId + ":" + channelId;
|
||||
String playKey = VideoManagerConstants.INVITE_INFO_1078_PLAY + deviceId + ":" + channelId;
|
||||
dynamicTask.stop(playKey);
|
||||
StreamInfo streamInfo = (StreamInfo) redisTemplate.opsForValue().get(playKey);
|
||||
// 发送停止命令
|
||||
@@ -205,6 +206,7 @@ public class jt1078ServiceImpl implements Ijt1078Service {
|
||||
j9102.setCloseType(0);
|
||||
j9102.setStreamType(1);
|
||||
jt1078Template.stopLive(deviceId, j9102, 6);
|
||||
logger.info("[1078-停止点播] deviceId: {}, channelId: {}", deviceId, channelId);
|
||||
// 删除缓存数据
|
||||
if (streamInfo != null) {
|
||||
// 关闭rtpServer
|
||||
@@ -218,4 +220,175 @@ public class jt1078ServiceImpl implements Ijt1078Service {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pausePlay(String deviceId, String channelId) {
|
||||
String playKey = VideoManagerConstants.INVITE_INFO_1078_PLAY + deviceId + ":" + channelId;
|
||||
dynamicTask.stop(playKey);
|
||||
StreamInfo streamInfo = (StreamInfo) redisTemplate.opsForValue().get(playKey);
|
||||
if (streamInfo == null) {
|
||||
logger.info("[1078-暂停点播] 未找到点播信息 deviceId: {}, channelId: {}", deviceId, channelId);
|
||||
}
|
||||
logger.info("[1078-暂停点播] deviceId: {}, channelId: {}", deviceId, channelId);
|
||||
// 发送暂停命令
|
||||
J9102 j9102 = new J9102();
|
||||
j9102.setChannel(Integer.valueOf(channelId));
|
||||
j9102.setCommand(2);
|
||||
j9102.setCloseType(0);
|
||||
j9102.setStreamType(1);
|
||||
jt1078Template.stopLive(deviceId, j9102, 6);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void continueLivePlay(String deviceId, String channelId) {
|
||||
String playKey = VideoManagerConstants.INVITE_INFO_1078_PLAY + deviceId + ":" + channelId;
|
||||
dynamicTask.stop(playKey);
|
||||
StreamInfo streamInfo = (StreamInfo) redisTemplate.opsForValue().get(playKey);
|
||||
if (streamInfo == null) {
|
||||
logger.info("[1078-继续点播] 未找到点播信息 deviceId: {}, channelId: {}", deviceId, channelId);
|
||||
}
|
||||
logger.info("[1078-继续点播] deviceId: {}, channelId: {}", deviceId, channelId);
|
||||
// 发送暂停命令
|
||||
J9102 j9102 = new J9102();
|
||||
j9102.setChannel(Integer.valueOf(channelId));
|
||||
j9102.setCommand(2);
|
||||
j9102.setCloseType(0);
|
||||
j9102.setStreamType(1);
|
||||
jt1078Template.stopLive(deviceId, j9102, 6);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<J1205.JRecordItem> getRecordList(String deviceId, String channelId, String startTime, String endTime) {
|
||||
logger.info("[1078-查询录像列表] deviceId: {}, channelId: {}, startTime: {}, endTime: {}"
|
||||
, deviceId, channelId, startTime, endTime);
|
||||
// 发送请求录像列表命令
|
||||
J9205 j9205 = new J9205();
|
||||
j9205.setChannelId(Integer.parseInt(channelId));
|
||||
j9205.setStartTime(DateUtil.yyyy_MM_dd_HH_mm_ssTo1078(startTime));
|
||||
j9205.setEndTime(DateUtil.yyyy_MM_dd_HH_mm_ssTo1078(endTime));
|
||||
j9205.setMediaType(0);
|
||||
j9205.setStreamType(0);
|
||||
j9205.setStorageType(0);
|
||||
String J1205JSON = jt1078Template.queryBackTime(deviceId, j9205, 20);
|
||||
if (J1205JSON == null) {
|
||||
return null;
|
||||
}
|
||||
J1205 j1205 = JSON.parseObject(J1205JSON, J1205.class);
|
||||
if (j1205 == null) {
|
||||
return null;
|
||||
}
|
||||
logger.info("[1078-查询录像列表] deviceId: {}, channelId: {}, startTime: {}, endTime: {}, 结果: {}条"
|
||||
, deviceId, channelId, startTime, endTime, j1205.getRecordList().size() );
|
||||
return j1205.getRecordList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playback(String deviceId, String channelId, String startTime, String endTime, GeneralCallback<StreamInfo> callback) {
|
||||
|
||||
// 检查流是否已经存在,存在则返回
|
||||
String playbackKey = VideoManagerConstants.INVITE_INFO_1078_PLAYBACK + deviceId + ":" + channelId;
|
||||
List<GeneralCallback<StreamInfo>> errorCallbacks = inviteErrorCallbackMap.computeIfAbsent(playbackKey, k -> new ArrayList<>());
|
||||
errorCallbacks.add(callback);
|
||||
String logInfo = String.format("deviceId:%s, channelId:%s, startTime:%s, endTime:%s", deviceId, channelId, startTime, endTime);
|
||||
StreamInfo streamInfo = (StreamInfo)redisTemplate.opsForValue().get(playbackKey);
|
||||
if (streamInfo != null) {
|
||||
String mediaServerId = streamInfo.getMediaServerId();
|
||||
MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
|
||||
if (mediaServerItem != null) {
|
||||
// 查询流是否存在,不存在则删除缓存数据
|
||||
JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, "rtp", "rtsp", streamInfo.getStream());
|
||||
if (mediaInfo != null && mediaInfo.getInteger("code") == 0 ) {
|
||||
Boolean online = mediaInfo.getBoolean("online");
|
||||
if (online != null && online) {
|
||||
logger.info("[1078-回放] 回放已经存在,直接返回, logInfo: {}", logInfo);
|
||||
for (GeneralCallback<StreamInfo> errorCallback : errorCallbacks) {
|
||||
errorCallback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 清理数据
|
||||
redisTemplate.delete(playbackKey);
|
||||
}
|
||||
String startTimeParam = DateUtil.yyyy_MM_dd_HH_mm_ssTo1078(startTime);
|
||||
String endTimeParam = DateUtil.yyyy_MM_dd_HH_mm_ssTo1078(endTime);
|
||||
String stream = deviceId + "-" + channelId + "-" + startTimeParam + "-" + endTimeParam;
|
||||
MediaServerItem mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(null);
|
||||
if (mediaServerItem == null) {
|
||||
for (GeneralCallback<StreamInfo> errorCallback : errorCallbacks) {
|
||||
errorCallback.run(InviteErrorCode.FAIL.getCode(), "未找到可用的媒体节点", streamInfo);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// 设置hook监听
|
||||
HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId());
|
||||
subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, HookParam hookParam) -> {
|
||||
OnStreamChangedHookParam streamChangedHookParam = (OnStreamChangedHookParam) hookParam;
|
||||
dynamicTask.stop(playbackKey);
|
||||
logger.info("[1078-回放] 回放成功, logInfo: {}", logInfo);
|
||||
StreamInfo info = onPublishHandler(mediaServerItemInUse, streamChangedHookParam, deviceId, channelId);
|
||||
|
||||
for (GeneralCallback<StreamInfo> errorCallback : errorCallbacks) {
|
||||
errorCallback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), info);
|
||||
}
|
||||
subscribe.removeSubscribe(hookSubscribe);
|
||||
redisTemplate.opsForValue().set(playbackKey, info);
|
||||
});
|
||||
// 设置超时监听
|
||||
dynamicTask.startDelay(playbackKey, () -> {
|
||||
logger.info("[1078-回放] 回放超时, logInfo: {}", logInfo);
|
||||
for (GeneralCallback<StreamInfo> errorCallback : errorCallbacks) {
|
||||
errorCallback.run(InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode(),
|
||||
InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getMsg(), null);
|
||||
}
|
||||
|
||||
}, userSetting.getPlayTimeout());
|
||||
|
||||
// 开启收流端口
|
||||
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, stream, null, false, false, 0, false, false, 1);
|
||||
logger.info("[1078-回放] logInfo: {}, 端口: {}", logInfo, ssrcInfo.getPort());
|
||||
J9201 j9201 = new J9201();
|
||||
j9201.setChannel(Integer.parseInt(channelId));
|
||||
j9201.setIp(mediaServerItem.getSdpIp());
|
||||
j9201.setRate(0);
|
||||
j9201.setPlaybackType(0);
|
||||
j9201.setPlaybackSpeed(0);
|
||||
j9201.setTcpPort(ssrcInfo.getPort());
|
||||
j9201.setUdpPort(ssrcInfo.getPort());
|
||||
j9201.setType(0);
|
||||
j9201.setStartTime(DateUtil.yyyy_MM_dd_HH_mm_ssTo1078(startTime));
|
||||
j9201.setEndTime(DateUtil.yyyy_MM_dd_HH_mm_ssTo1078(endTime));
|
||||
String s = jt1078Template.startBackLive(deviceId, j9201, 20);
|
||||
System.out.println("111ssss=== " + s);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopPlayback(String deviceId, String channelId) {
|
||||
String playKey = VideoManagerConstants.INVITE_INFO_1078_PLAYBACK + deviceId + ":" + channelId;
|
||||
dynamicTask.stop(playKey);
|
||||
StreamInfo streamInfo = (StreamInfo) redisTemplate.opsForValue().get(playKey);
|
||||
// 发送停止命令
|
||||
J9202 j9202 = new J9202();
|
||||
j9202.setChannel(Integer.parseInt(channelId));
|
||||
j9202.setPlaybackType(0);
|
||||
j9202.setPlaybackSpeed(0);
|
||||
j9202.setPlaybackTime("");
|
||||
jt1078Template.controlBackLive(deviceId, j9202, 6);
|
||||
logger.info("[1078-停止回放] deviceId: {}, channelId: {}", deviceId, channelId);
|
||||
// 删除缓存数据
|
||||
if (streamInfo != null) {
|
||||
// 关闭rtpServer
|
||||
mediaServerService.closeRTPServer(streamInfo.getMediaServerId(), streamInfo.getStream());
|
||||
}
|
||||
// 清理回调
|
||||
List<GeneralCallback<StreamInfo>> generalCallbacks = inviteErrorCallbackMap.get(playKey);
|
||||
if (!generalCallbacks.isEmpty()) {
|
||||
for (GeneralCallback<StreamInfo> callback : generalCallbacks) {
|
||||
callback.run(InviteErrorCode.ERROR_FOR_FINISH.getCode(), InviteErrorCode.ERROR_FOR_FINISH.getMsg(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ public class DateUtil {
|
||||
* wvp内部统一时间格式
|
||||
*/
|
||||
public static final String URL_PATTERN = "yyyyMMddHHmmss";
|
||||
public static final String PATTERN1078 = "yyMMddHHmmss";
|
||||
|
||||
/**
|
||||
* 日期格式
|
||||
@@ -65,6 +66,7 @@ public class DateUtil {
|
||||
public static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(PATTERN, Locale.getDefault()).withZone(ZoneId.of(zoneStr));
|
||||
public static final DateTimeFormatter DateFormatter = DateTimeFormatter.ofPattern(date_PATTERN, Locale.getDefault()).withZone(ZoneId.of(zoneStr));
|
||||
public static final DateTimeFormatter urlFormatter = DateTimeFormatter.ofPattern(URL_PATTERN, Locale.getDefault()).withZone(ZoneId.of(zoneStr));
|
||||
public static final DateTimeFormatter formatter1078 = DateTimeFormatter.ofPattern(PATTERN1078, Locale.getDefault()).withZone(ZoneId.of(zoneStr));
|
||||
|
||||
public static String yyyy_MM_dd_HH_mm_ssToISO8601(String formatTime) {
|
||||
|
||||
@@ -86,6 +88,9 @@ public class DateUtil {
|
||||
public static String urlToyyyy_MM_dd_HH_mm_ss(String formatTime) {
|
||||
return formatter.format(urlFormatter.parse(formatTime));
|
||||
}
|
||||
public static String yyyy_MM_dd_HH_mm_ssTo1078(String formatTime) {
|
||||
return formatter1078.format(formatter.parse(formatTime));
|
||||
}
|
||||
|
||||
/**
|
||||
* yyyy_MM_dd_HH_mm_ss 转时间戳
|
||||
|
||||
@@ -10,6 +10,7 @@ public enum ErrorCode {
|
||||
ERROR404(404, "资源未找到"),
|
||||
ERROR403(403, "无权限操作"),
|
||||
ERROR401(401, "请登录后重新请求"),
|
||||
ERROR408(408, "请求超时"),
|
||||
ERROR500(500, "系统异常");
|
||||
|
||||
private final int code;
|
||||
|
||||
Reference in New Issue
Block a user