修复国标录像回放以及录像下载

This commit is contained in:
648540858 2023-01-06 11:43:27 +08:00
parent d03e8b0428
commit fd3a4ef472
11 changed files with 158 additions and 111 deletions

View File

@ -45,6 +45,8 @@ public class UserSetting {
private Boolean syncChannelOnDeviceOnline = Boolean.FALSE; private Boolean syncChannelOnDeviceOnline = Boolean.FALSE;
private Boolean sipLog = Boolean.FALSE;
private String serverId = "000000"; private String serverId = "000000";
private String thirdPartyGBIdReg = "[\\s\\S]*"; private String thirdPartyGBIdReg = "[\\s\\S]*";
@ -206,4 +208,12 @@ public class UserSetting {
public void setSipUseSourceIpAsRemoteAddress(Boolean sipUseSourceIpAsRemoteAddress) { public void setSipUseSourceIpAsRemoteAddress(Boolean sipUseSourceIpAsRemoteAddress) {
this.sipUseSourceIpAsRemoteAddress = sipUseSourceIpAsRemoteAddress; this.sipUseSourceIpAsRemoteAddress = sipUseSourceIpAsRemoteAddress;
} }
public Boolean getSipLog() {
return sipLog;
}
public void setSipLog(Boolean sipLog) {
this.sipLog = sipLog;
}
} }

View File

@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.gb28181; package com.genersoft.iot.vmp.gb28181;
import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.conf.DefaultProperties; import com.genersoft.iot.vmp.gb28181.conf.DefaultProperties;
import com.genersoft.iot.vmp.gb28181.transmit.ISIPProcessorObserver; import com.genersoft.iot.vmp.gb28181.transmit.ISIPProcessorObserver;
import gov.nist.javax.sip.SipProviderImpl; import gov.nist.javax.sip.SipProviderImpl;
@ -29,6 +30,9 @@ public class SipLayer implements CommandLineRunner {
@Autowired @Autowired
private ISIPProcessorObserver sipProcessorObserver; private ISIPProcessorObserver sipProcessorObserver;
@Autowired
private UserSetting userSetting;
private final Map<String, SipProviderImpl> tcpSipProviderMap = new ConcurrentHashMap<>(); private final Map<String, SipProviderImpl> tcpSipProviderMap = new ConcurrentHashMap<>();
private final Map<String, SipProviderImpl> udpSipProviderMap = new ConcurrentHashMap<>(); private final Map<String, SipProviderImpl> udpSipProviderMap = new ConcurrentHashMap<>();
@ -61,7 +65,7 @@ public class SipLayer implements CommandLineRunner {
private void addListeningPoint(String monitorIp, int port){ private void addListeningPoint(String monitorIp, int port){
SipStackImpl sipStack; SipStackImpl sipStack;
try { try {
sipStack = (SipStackImpl)sipFactory.createSipStack(DefaultProperties.getProperties(monitorIp, false)); sipStack = (SipStackImpl)sipFactory.createSipStack(DefaultProperties.getProperties(monitorIp, false, userSetting.getSipLog()));
} catch (PeerUnavailableException e) { } catch (PeerUnavailableException e) {
logger.error("[Sip Server] SIP服务启动失败 监听地址{}失败,请检查ip是否正确", monitorIp); logger.error("[Sip Server] SIP服务启动失败 监听地址{}失败,请检查ip是否正确", monitorIp);
return; return;

View File

@ -12,7 +12,7 @@ import java.util.Properties;
*/ */
public class DefaultProperties { public class DefaultProperties {
public static Properties getProperties(String ip, boolean isDebug) { public static Properties getProperties(String ip, boolean isDebug, boolean sipLog) {
Properties properties = new Properties(); Properties properties = new Properties();
properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP"); properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP");
properties.setProperty("javax.sip.IP_ADDRESS", ip); properties.setProperty("javax.sip.IP_ADDRESS", ip);
@ -49,23 +49,28 @@ public class DefaultProperties {
* sip_server_log.log sip_debug_log.log ERROR, INFO, WARNING, OFF, DEBUG, TRACE * sip_server_log.log sip_debug_log.log ERROR, INFO, WARNING, OFF, DEBUG, TRACE
*/ */
Logger logger = LoggerFactory.getLogger(AlarmNotifyMessageHandler.class); Logger logger = LoggerFactory.getLogger(AlarmNotifyMessageHandler.class);
if (logger.isDebugEnabled()) { if (sipLog) {
System.out.println("DEBUG"); if (logger.isDebugEnabled()) {
properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "DEBUG"); System.out.println("DEBUG");
}else if (logger.isInfoEnabled()) { properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "DEBUG");
System.out.println("INFO1"); }else if (logger.isInfoEnabled()) {
properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "INFO"); System.out.println("INFO1");
}else if (logger.isWarnEnabled()) { properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "INFO");
System.out.println("WARNING"); }else if (logger.isWarnEnabled()) {
properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "WARNING"); System.out.println("WARNING");
}else if (logger.isErrorEnabled()) { properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "WARNING");
System.out.println("ERROR"); }else if (logger.isErrorEnabled()) {
properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "ERROR"); System.out.println("ERROR");
properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "ERROR");
}else {
System.out.println("INFO2");
properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "INFO");
}
logger.info("[SIP日志]级别为: {}", properties.getProperty("gov.nist.javax.sip.TRACE_LEVEL"));
}else { }else {
System.out.println("INFO2"); logger.info("[SIP日志]已关闭");
properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "INFO");
} }
logger.info("[SIP日志]级别为: {}", properties.getProperty("gov.nist.javax.sip.TRACE_LEVEL"));
return properties; return properties;

View File

@ -12,8 +12,6 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.bean.InviteTimeOutCallback; import com.genersoft.iot.vmp.service.bean.InviteTimeOutCallback;
import com.genersoft.iot.vmp.service.bean.PlayBackCallback; import com.genersoft.iot.vmp.service.bean.PlayBackCallback;
import com.genersoft.iot.vmp.service.bean.SSRCInfo; import com.genersoft.iot.vmp.service.bean.SSRCInfo;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import org.springframework.web.context.request.async.DeferredResult;
import javax.sip.InvalidArgumentException; import javax.sip.InvalidArgumentException;
import javax.sip.SipException; import javax.sip.SipException;
@ -35,13 +33,13 @@ public interface IPlayService {
void onPublishHandlerForDownload(InviteStreamInfo inviteStreamInfo, String deviceId, String channelId, String toString); void onPublishHandlerForDownload(InviteStreamInfo inviteStreamInfo, String deviceId, String channelId, String toString);
DeferredResult<WVPResult<StreamInfo>> playBack(String deviceId, String channelId, String startTime, String endTime, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack); void playBack(String deviceId, String channelId, String startTime, String endTime, InviteStreamCallback infoCallBack, PlayBackCallback playBackCallback);
DeferredResult<WVPResult<StreamInfo>> playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId, String channelId, String startTime, String endTime, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack); void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack);
void zlmServerOffline(String mediaServerId); void zlmServerOffline(String mediaServerId);
DeferredResult<WVPResult<StreamInfo>> download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack); void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback playBackCallback);
DeferredResult<WVPResult<StreamInfo>> download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack); void download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack);
StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream); StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream);

View File

@ -1,10 +1,7 @@
package com.genersoft.iot.vmp.service.bean; package com.genersoft.iot.vmp.service.bean;
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; public interface PlayBackCallback<T> {
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
public interface PlayBackCallback { void call(PlayBackResult<T> msg);
void call(PlayBackResult<RequestMessage> msg);
} }

View File

@ -43,7 +43,6 @@ import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.web.context.request.async.DeferredResult;
import javax.sip.InvalidArgumentException; import javax.sip.InvalidArgumentException;
import javax.sip.ResponseEvent; import javax.sip.ResponseEvent;
@ -381,14 +380,10 @@ public class PlayServiceImpl implements IPlayService {
} }
} }
private void onPublishHandlerForPlayback(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, String uuid) { private void onPublishHandlerForPlayback(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, PlayBackCallback playBackCallback) {
RequestMessage msg = new RequestMessage();
msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId);
if (!ObjectUtils.isEmpty(uuid)) {
msg.setId(uuid);
}
StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId);
StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId);
PlayBackResult<StreamInfo> playBackResult = new PlayBackResult<>();
if (streamInfo != null) { if (streamInfo != null) {
DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId);
if (deviceChannel != null) { if (deviceChannel != null) {
@ -397,17 +392,16 @@ public class PlayServiceImpl implements IPlayService {
} }
redisCatchStorage.startPlay(streamInfo); redisCatchStorage.startPlay(streamInfo);
WVPResult wvpResult = new WVPResult();
wvpResult.setCode(ErrorCode.SUCCESS.getCode());
wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());
wvpResult.setData(streamInfo);
msg.setData(wvpResult);
resultHolder.invokeAllResult(msg); playBackResult.setCode(ErrorCode.SUCCESS.getCode());
playBackResult.setMsg(ErrorCode.SUCCESS.getMsg());
playBackResult.setData(streamInfo);
playBackCallback.call(playBackResult);
} else { } else {
logger.warn("录像回放调用失败!"); logger.warn("录像回放调用失败!");
msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), "录像回放调用失败!")); playBackResult.setCode(ErrorCode.ERROR100.getCode());
resultHolder.invokeAllResult(msg); playBackResult.setMsg("录像回放调用失败!");
playBackCallback.call(playBackResult);
} }
} }
@ -429,45 +423,39 @@ public class PlayServiceImpl implements IPlayService {
} }
@Override @Override
public DeferredResult<WVPResult<StreamInfo>> playBack(String deviceId, String channelId, String startTime, public void playBack(String deviceId, String channelId, String startTime,
String endTime, InviteStreamCallback inviteStreamCallback, String endTime, InviteStreamCallback inviteStreamCallback,
PlayBackCallback callback) { PlayBackCallback callback) {
Device device = storager.queryVideoDevice(deviceId); Device device = storager.queryVideoDevice(deviceId);
if (device == null) { if (device == null) {
return null; return;
} }
MediaServerItem newMediaServerItem = getNewMediaServerItem(device); MediaServerItem newMediaServerItem = getNewMediaServerItem(device);
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, device.isSsrcCheck(), true); SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, device.isSsrcCheck(), true);
return playBack(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, inviteStreamCallback, callback); playBack(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, inviteStreamCallback, callback);
} }
@Override @Override
public DeferredResult<WVPResult<StreamInfo>> playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, public void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,
String deviceId, String channelId, String startTime, String deviceId, String channelId, String startTime,
String endTime, InviteStreamCallback infoCallBack, String endTime, InviteStreamCallback infoCallBack,
PlayBackCallback playBackCallback) { PlayBackCallback playBackCallback) {
if (mediaServerItem == null || ssrcInfo == null) { if (mediaServerItem == null || ssrcInfo == null) {
return null; return;
} }
String uuid = UUID.randomUUID().toString();
String key = DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId;
Device device = storager.queryVideoDevice(deviceId); Device device = storager.queryVideoDevice(deviceId);
if (device == null) { if (device == null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备: " + deviceId + "不存在"); throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备: " + deviceId + "不存在");
} }
DeferredResult<WVPResult<StreamInfo>> result = new DeferredResult<>(30000L);
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId, uuid, result); PlayBackResult<StreamInfo> playBackResult = new PlayBackResult<>();
RequestMessage requestMessage = new RequestMessage();
requestMessage.setId(uuid);
requestMessage.setKey(key);
PlayBackResult<RequestMessage> playBackResult = new PlayBackResult<>();
String playBackTimeOutTaskKey = UUID.randomUUID().toString(); String playBackTimeOutTaskKey = UUID.randomUUID().toString();
dynamicTask.startDelay(playBackTimeOutTaskKey, () -> { dynamicTask.startDelay(playBackTimeOutTaskKey, () -> {
logger.warn(String.format("设备回放超时deviceId%s channelId%s", deviceId, channelId)); logger.warn(String.format("设备回放超时deviceId%s channelId%s", deviceId, channelId));
playBackResult.setCode(ErrorCode.ERROR100.getCode()); playBackResult.setCode(ErrorCode.ERROR100.getCode());
playBackResult.setMsg("回放超时"); playBackResult.setMsg("回放超时");
playBackResult.setData(requestMessage);
try { try {
cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null); cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null);
@ -479,19 +467,14 @@ public class PlayServiceImpl implements IPlayService {
mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
streamSession.remove(deviceId, channelId, ssrcInfo.getStream()); streamSession.remove(deviceId, channelId, ssrcInfo.getStream());
} }
// 回复之前所有的点播请求 // 回复之前所有的点播请求
playBackCallback.call(playBackResult); playBackCallback.call(playBackResult);
result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "回放超时"));
resultHolder.exist(DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId, uuid);
}, userSetting.getPlayTimeout()); }, userSetting.getPlayTimeout());
SipSubscribe.Event errorEvent = event -> { SipSubscribe.Event errorEvent = event -> {
dynamicTask.stop(playBackTimeOutTaskKey); dynamicTask.stop(playBackTimeOutTaskKey);
requestMessage.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg)));
playBackResult.setCode(ErrorCode.ERROR100.getCode()); playBackResult.setCode(ErrorCode.ERROR100.getCode());
playBackResult.setMsg(String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg)); playBackResult.setMsg(String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg));
playBackResult.setData(requestMessage);
playBackResult.setEvent(event); playBackResult.setEvent(event);
playBackCallback.call(playBackResult); playBackCallback.call(playBackResult);
streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
@ -509,11 +492,9 @@ public class PlayServiceImpl implements IPlayService {
return; return;
} }
redisCatchStorage.startPlayback(streamInfo, inviteStreamInfo.getCallId()); redisCatchStorage.startPlayback(streamInfo, inviteStreamInfo.getCallId());
WVPResult<StreamInfo> success = WVPResult.success(streamInfo);
requestMessage.setData(success);
playBackResult.setCode(ErrorCode.SUCCESS.getCode()); playBackResult.setCode(ErrorCode.SUCCESS.getCode());
playBackResult.setMsg(ErrorCode.SUCCESS.getMsg()); playBackResult.setMsg(ErrorCode.SUCCESS.getMsg());
playBackResult.setData(requestMessage); playBackResult.setData(streamInfo);
playBackResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem()); playBackResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem());
playBackResult.setResponse(inviteStreamInfo.getResponse()); playBackResult.setResponse(inviteStreamInfo.getResponse());
playBackCallback.call(playBackResult); playBackCallback.call(playBackResult);
@ -560,7 +541,7 @@ public class PlayServiceImpl implements IPlayService {
logger.info("[ZLM HOOK] ssrc修正后收到订阅消息 " + response.toJSONString()); logger.info("[ZLM HOOK] ssrc修正后收到订阅消息 " + response.toJSONString());
dynamicTask.stop(playBackTimeOutTaskKey); dynamicTask.stop(playBackTimeOutTaskKey);
// hook响应 // hook响应
onPublishHandlerForPlayback(mediaServerItemInUse, response, device.getDeviceId(), channelId, uuid); onPublishHandlerForPlayback(mediaServerItemInUse, response, device.getDeviceId(), channelId, playBackCallback);
hookEvent.call(new InviteStreamInfo(mediaServerItem, null, eventResult.callId, "rtp", ssrcInfo.getStream())); hookEvent.call(new InviteStreamInfo(mediaServerItem, null, eventResult.callId, "rtp", ssrcInfo.getStream()));
}); });
} }
@ -580,50 +561,37 @@ public class PlayServiceImpl implements IPlayService {
eventResult.msg = "命令发送失败"; eventResult.msg = "命令发送失败";
errorEvent.response(eventResult); errorEvent.response(eventResult);
} }
return result;
} }
@Override @Override
public DeferredResult<WVPResult<StreamInfo>> download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack) { public void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack) {
Device device = storager.queryVideoDevice(deviceId); Device device = storager.queryVideoDevice(deviceId);
if (device == null) { if (device == null) {
return null; return;
} }
MediaServerItem newMediaServerItem = getNewMediaServerItem(device); MediaServerItem newMediaServerItem = getNewMediaServerItem(device);
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, device.isSsrcCheck(), true); SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, device.isSsrcCheck(), true);
return download(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, downloadSpeed, infoCallBack, hookCallBack); download(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, downloadSpeed, infoCallBack, hookCallBack);
} }
@Override @Override
public DeferredResult<WVPResult<StreamInfo>> download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack) { public void download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack) {
if (mediaServerItem == null || ssrcInfo == null) { if (mediaServerItem == null || ssrcInfo == null) {
return null; return;
} }
String uuid = UUID.randomUUID().toString();
String key = DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId;
DeferredResult<WVPResult<StreamInfo>> result = new DeferredResult<>(30000L);
Device device = storager.queryVideoDevice(deviceId); Device device = storager.queryVideoDevice(deviceId);
if (device == null) { if (device == null) {
throw new ControllerException(ErrorCode.ERROR400.getCode(), "设备:" + deviceId + "不存在"); throw new ControllerException(ErrorCode.ERROR400.getCode(), "设备:" + deviceId + "不存在");
} }
PlayBackResult<StreamInfo> downloadResult = new PlayBackResult<>();
resultHolder.put(key, uuid, result);
RequestMessage requestMessage = new RequestMessage();
requestMessage.setId(uuid);
requestMessage.setKey(key);
WVPResult<StreamInfo> wvpResult = new WVPResult<>();
requestMessage.setData(wvpResult);
PlayBackResult<RequestMessage> downloadResult = new PlayBackResult<>();
downloadResult.setData(requestMessage);
String downLoadTimeOutTaskKey = UUID.randomUUID().toString(); String downLoadTimeOutTaskKey = UUID.randomUUID().toString();
dynamicTask.startDelay(downLoadTimeOutTaskKey, () -> { dynamicTask.startDelay(downLoadTimeOutTaskKey, () -> {
logger.warn(String.format("录像下载请求超时deviceId%s channelId%s", deviceId, channelId)); logger.warn(String.format("录像下载请求超时deviceId%s channelId%s", deviceId, channelId));
wvpResult.setCode(ErrorCode.ERROR100.getCode());
wvpResult.setMsg("录像下载请求超时");
downloadResult.setCode(ErrorCode.ERROR100.getCode()); downloadResult.setCode(ErrorCode.ERROR100.getCode());
downloadResult.setMsg("录像下载请求超时"); downloadResult.setMsg("录像下载请求超时");
hookCallBack.call(downloadResult); hookCallBack.call(downloadResult);
@ -638,16 +606,12 @@ public class PlayServiceImpl implements IPlayService {
mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
streamSession.remove(deviceId, channelId, ssrcInfo.getStream()); streamSession.remove(deviceId, channelId, ssrcInfo.getStream());
} }
// 回复之前所有的点播请求
hookCallBack.call(downloadResult);
}, userSetting.getPlayTimeout()); }, userSetting.getPlayTimeout());
SipSubscribe.Event errorEvent = event -> { SipSubscribe.Event errorEvent = event -> {
dynamicTask.stop(downLoadTimeOutTaskKey); dynamicTask.stop(downLoadTimeOutTaskKey);
downloadResult.setCode(ErrorCode.ERROR100.getCode()); downloadResult.setCode(ErrorCode.ERROR100.getCode());
downloadResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg)); downloadResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg));
wvpResult.setCode(ErrorCode.ERROR100.getCode());
wvpResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg));
downloadResult.setEvent(event); downloadResult.setEvent(event);
hookCallBack.call(downloadResult); hookCallBack.call(downloadResult);
streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
@ -662,11 +626,9 @@ public class PlayServiceImpl implements IPlayService {
streamInfo.setStartTime(startTime); streamInfo.setStartTime(startTime);
streamInfo.setEndTime(endTime); streamInfo.setEndTime(endTime);
redisCatchStorage.startDownload(streamInfo, inviteStreamInfo.getCallId()); redisCatchStorage.startDownload(streamInfo, inviteStreamInfo.getCallId());
wvpResult.setCode(ErrorCode.SUCCESS.getCode());
wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());
wvpResult.setData(streamInfo);
downloadResult.setCode(ErrorCode.SUCCESS.getCode()); downloadResult.setCode(ErrorCode.SUCCESS.getCode());
downloadResult.setMsg(ErrorCode.SUCCESS.getMsg()); downloadResult.setMsg(ErrorCode.SUCCESS.getMsg());
downloadResult.setData(streamInfo);
downloadResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem()); downloadResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem());
downloadResult.setResponse(inviteStreamInfo.getResponse()); downloadResult.setResponse(inviteStreamInfo.getResponse());
hookCallBack.call(downloadResult); hookCallBack.call(downloadResult);
@ -678,7 +640,6 @@ public class PlayServiceImpl implements IPlayService {
eventResult.msg = "命令发送失败"; eventResult.msg = "命令发送失败";
errorEvent.response(eventResult); errorEvent.response(eventResult);
} }
return result;
} }
@Override @Override

View File

@ -1,7 +1,5 @@
package com.genersoft.iot.vmp.vmanager.bean; package com.genersoft.iot.vmp.vmanager.bean;
import io.swagger.v3.oas.annotations.media.Schema;
/** /**
* 全局错误码 * 全局错误码
*/ */
@ -9,6 +7,7 @@ public enum ErrorCode {
SUCCESS(0, "成功"), SUCCESS(0, "成功"),
ERROR100(100, "失败"), ERROR100(100, "失败"),
ERROR400(400, "参数不全或者错误"), ERROR400(400, "参数不全或者错误"),
ERROR404(404, "资源未找到"),
ERROR403(403, "无权限操作"), ERROR403(403, "无权限操作"),
ERROR401(401, "请登录后重新请求"), ERROR401(401, "请登录后重新请求"),
ERROR500(500, "系统异常"); ERROR500(500, "系统异常");

View File

@ -36,6 +36,12 @@ public class StreamContent {
private String mediaServerId; private String mediaServerId;
private Object tracks; private Object tracks;
private String startTime;
private String endTime;
private double progress;
public StreamContent(StreamInfo streamInfo) { public StreamContent(StreamInfo streamInfo) {
if (streamInfo == null) { if (streamInfo == null) {
return; return;
@ -105,6 +111,9 @@ public class StreamContent {
this.mediaServerId = streamInfo.getMediaServerId(); this.mediaServerId = streamInfo.getMediaServerId();
this.tracks = streamInfo.getTracks(); this.tracks = streamInfo.getTracks();
this.startTime = streamInfo.getStartTime();
this.endTime = streamInfo.getEndTime();
this.progress = streamInfo.getProgress();
} }
public String getApp() { public String getApp() {
@ -322,4 +331,28 @@ public class StreamContent {
public void setTracks(Object tracks) { public void setTracks(Object tracks) {
this.tracks = tracks; this.tracks = tracks;
} }
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 double getProgress() {
return progress;
}
public void setProgress(double progress) {
this.progress = progress;
}
} }

View File

@ -10,6 +10,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.service.IPlayService; import com.genersoft.iot.vmp.service.IPlayService;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 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.bean.WVPResult;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
@ -32,6 +33,7 @@ import org.springframework.web.context.request.async.DeferredResult;
import javax.sip.InvalidArgumentException; import javax.sip.InvalidArgumentException;
import javax.sip.SipException; import javax.sip.SipException;
import java.text.ParseException; import java.text.ParseException;
import java.util.UUID;
/** /**
* @author lin * @author lin
@ -68,24 +70,37 @@ public class PlaybackController {
@Parameter(name = "startTime", description = "开始时间", required = true) @Parameter(name = "startTime", description = "开始时间", required = true)
@Parameter(name = "endTime", description = "结束时间", required = true) @Parameter(name = "endTime", description = "结束时间", required = true)
@GetMapping("/start/{deviceId}/{channelId}") @GetMapping("/start/{deviceId}/{channelId}")
public DeferredResult<WVPResult<StreamInfo>> play(@PathVariable String deviceId, @PathVariable String channelId, public DeferredResult<WVPResult<StreamContent>> play(@PathVariable String deviceId, @PathVariable String channelId,
String startTime, String endTime) { String startTime, String endTime) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug(String.format("设备回放 API调用deviceId%s channelId%s", deviceId, channelId)); logger.debug(String.format("设备回放 API调用deviceId%s channelId%s", deviceId, channelId));
} }
String uuid = UUID.randomUUID().toString();
String key = DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId;
DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>(30000L);
resultHolder.put(key, uuid, result);
return playService.playBack(deviceId, channelId, startTime, endTime, null, WVPResult<StreamContent> wvpResult = new WVPResult<>();
RequestMessage msg = new RequestMessage();
msg.setKey(key);
msg.setId(uuid);
playService.playBack(deviceId, channelId, startTime, endTime, null,
playBackResult->{ playBackResult->{
if (playBackResult.getCode() != ErrorCode.SUCCESS.getCode()) { wvpResult.setCode(playBackResult.getCode());
RequestMessage data = playBackResult.getData(); wvpResult.setMsg(playBackResult.getMsg());
data.setData(WVPResult.fail(playBackResult.getCode(), playBackResult.getMsg())); if (playBackResult.getCode() == ErrorCode.SUCCESS.getCode()) {
resultHolder.invokeResult(data); StreamInfo streamInfo = (StreamInfo)playBackResult.getData();
}else { wvpResult.setData(new StreamContent(streamInfo));
resultHolder.invokeResult(playBackResult.getData());
} }
msg.setData(wvpResult);
resultHolder.invokeResult(msg);
}); });
return result;
} }

View File

@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.service.IDeviceService;
import com.genersoft.iot.vmp.service.IPlayService; import com.genersoft.iot.vmp.service.IPlayService;
import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 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.bean.WVPResult;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
@ -121,15 +122,33 @@ public class GBRecordController {
@Parameter(name = "endTime", description = "结束时间", required = true) @Parameter(name = "endTime", description = "结束时间", required = true)
@Parameter(name = "downloadSpeed", description = "下载倍速", required = true) @Parameter(name = "downloadSpeed", description = "下载倍速", required = true)
@GetMapping("/download/start/{deviceId}/{channelId}") @GetMapping("/download/start/{deviceId}/{channelId}")
public DeferredResult<WVPResult<StreamInfo>> download(@PathVariable String deviceId, @PathVariable String channelId, public DeferredResult<WVPResult<StreamContent>> download(@PathVariable String deviceId, @PathVariable String channelId,
String startTime, String endTime, String downloadSpeed) { String startTime, String endTime, String downloadSpeed) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug(String.format("历史媒体下载 API调用deviceId%schannelId%sdownloadSpeed%s", deviceId, channelId, downloadSpeed)); logger.debug(String.format("历史媒体下载 API调用deviceId%schannelId%sdownloadSpeed%s", deviceId, channelId, downloadSpeed));
} }
DeferredResult<WVPResult<StreamInfo>> result = playService.download(deviceId, channelId, startTime, endTime, Integer.parseInt(downloadSpeed), null, hookCallBack->{ String uuid = UUID.randomUUID().toString();
resultHolder.invokeResult(hookCallBack.getData()); String key = DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId;
DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>(30000L);
resultHolder.put(key, uuid, result);
RequestMessage msg = new RequestMessage();
msg.setId(uuid);
msg.setKey(key);
WVPResult<StreamContent> wvpResult = new WVPResult<>();
playService.download(deviceId, channelId, startTime, endTime, Integer.parseInt(downloadSpeed), null, playBackResult->{
wvpResult.setCode(playBackResult.getCode());
wvpResult.setMsg(playBackResult.getMsg());
if (playBackResult.getCode() == ErrorCode.SUCCESS.getCode()) {
StreamInfo streamInfo = (StreamInfo)playBackResult.getData();
wvpResult.setData(new StreamContent(streamInfo));
}
msg.setData(wvpResult);
resultHolder.invokeResult(msg);
}); });
return result; return result;
@ -168,7 +187,11 @@ public class GBRecordController {
@Parameter(name = "channelId", description = "通道国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号", required = true)
@Parameter(name = "stream", description = "流ID", required = true) @Parameter(name = "stream", description = "流ID", required = true)
@GetMapping("/download/progress/{deviceId}/{channelId}/{stream}") @GetMapping("/download/progress/{deviceId}/{channelId}/{stream}")
public StreamInfo getProgress(@PathVariable String deviceId, @PathVariable String channelId, @PathVariable String stream) { public StreamContent getProgress(@PathVariable String deviceId, @PathVariable String channelId, @PathVariable String stream) {
return playService.getDownLoadInfo(deviceId, channelId, stream); StreamInfo downLoadInfo = playService.getDownLoadInfo(deviceId, channelId, stream);
if (downLoadInfo == null) {
throw new ControllerException(ErrorCode.ERROR404);
}
return new StreamContent(downLoadInfo);
} }
} }

View File

@ -197,6 +197,8 @@ user-settings:
sync-channel-on-device-online: false sync-channel-on-device-online: false
# 是否使用设备来源Ip作为回复IP 不设置则为 false # 是否使用设备来源Ip作为回复IP 不设置则为 false
sip-use-source-ip-as-remote-address: false sip-use-source-ip-as-remote-address: false
# 是否开启sip日志
sip-log: true
# 关闭在线文档(生产环境建议关闭) # 关闭在线文档(生产环境建议关闭)
springdoc: springdoc: