Commit 59d8f2f9152b3c3106abae64bef343cde842f225

Authored by 648540858
1 parent 51634b1b

支持录像回放使用固定流地址以及自动点播录像回放

sql/2.6.9更新.sql 0 → 100644
  1 +alter table wvp_device_channel
  2 + change stream_id stream_id varying(255)
0 3 \ No newline at end of file
... ...
sql/初始化.sql
... ... @@ -79,7 +79,7 @@ create table wvp_device_channel (
79 79 custom_longitude double precision,
80 80 latitude double precision,
81 81 custom_latitude double precision,
82   - stream_id character varying(50),
  82 + stream_id character varying(255),
83 83 device_id character varying(50) not null,
84 84 parental character varying(50),
85 85 has_audio bool default false,
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
... ... @@ -59,6 +59,7 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
59 59 // 未注册的设备不做处理
60 60 return;
61 61 }
  62 + logger.info("[收到心跳], device: {}", device.getDeviceId());
62 63 SIPRequest request = (SIPRequest) evt.getRequest();
63 64 // 回复200 OK
64 65 try {
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
... ... @@ -24,8 +24,10 @@ import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
24 24 import com.genersoft.iot.vmp.media.zlm.dto.hook.*;
25 25 import com.genersoft.iot.vmp.service.*;
26 26 import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
  27 +import com.genersoft.iot.vmp.service.bean.SSRCInfo;
27 28 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
28 29 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
  30 +import com.genersoft.iot.vmp.utils.DateUtil;
29 31 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
30 32 import com.genersoft.iot.vmp.vmanager.bean.OtherRtpSendInfo;
31 33 import com.genersoft.iot.vmp.vmanager.bean.StreamContent;
... ... @@ -559,7 +561,7 @@ public class ZLMHttpHookListener {
559 561  
560 562 if ("rtp".equals(param.getApp())) {
561 563 String[] s = param.getStream().split("_");
562   - if (!mediaInfo.isRtpEnable() || s.length != 2) {
  564 + if (!mediaInfo.isRtpEnable() || (s.length != 2 && s.length != 4)) {
563 565 defaultResult.setResult(HookResult.SUCCESS());
564 566 return defaultResult;
565 567 }
... ... @@ -575,33 +577,79 @@ public class ZLMHttpHookListener {
575 577 defaultResult.setResult(new HookResult(ErrorCode.ERROR404.getCode(), ErrorCode.ERROR404.getMsg()));
576 578 return defaultResult;
577 579 }
578   - logger.info("[ZLM HOOK] 流未找到, 发起自动点播:{}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream());
579   -
580   - RequestMessage msg = new RequestMessage();
581   - String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId;
582   - boolean exist = resultHolder.exist(key, null);
583   - msg.setKey(key);
584   - String uuid = UUID.randomUUID().toString();
585   - msg.setId(uuid);
586   - DeferredResult<HookResult> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue());
587   -
588   - result.onTimeout(() -> {
589   - logger.info("[ZLM HOOK] 自动点播, 等待超时");
590   - // 释放rtpserver
591   - msg.setData(new HookResult(ErrorCode.ERROR100.getCode(), "点播超时"));
592   - resultHolder.invokeResult(msg);
593   - });
594   -
595   - // 录像查询以channelId作为deviceId查询
596   - resultHolder.put(key, uuid, result);
597   -
598   - if (!exist) {
599   - playService.play(mediaInfo, deviceId, channelId, null, (code, message, data) -> {
600   - msg.setData(new HookResult(code, message));
  580 + if (s.length == 2) {
  581 + logger.info("[ZLM HOOK] 预览流未找到, 发起自动点播:{}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream());
  582 +
  583 + RequestMessage msg = new RequestMessage();
  584 + String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId;
  585 + boolean exist = resultHolder.exist(key, null);
  586 + msg.setKey(key);
  587 + String uuid = UUID.randomUUID().toString();
  588 + msg.setId(uuid);
  589 + DeferredResult<HookResult> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue());
  590 +
  591 + result.onTimeout(() -> {
  592 + logger.info("[ZLM HOOK] 预览流自动点播, 等待超时");
  593 + // 释放rtpserver
  594 + msg.setData(new HookResult(ErrorCode.ERROR100.getCode(), "点播超时"));
601 595 resultHolder.invokeResult(msg);
602 596 });
  597 +
  598 + resultHolder.put(key, uuid, result);
  599 +
  600 + if (!exist) {
  601 + playService.play(mediaInfo, deviceId, channelId, null, (code, message, data) -> {
  602 + msg.setData(new HookResult(code, message));
  603 + resultHolder.invokeResult(msg);
  604 + });
  605 + }
  606 + return result;
  607 + }else if(s.length == 4){
  608 + // 此时为录像回放, 录像回放格式为> 设备ID_通道ID_开始时间_结束时间
  609 + String startTimeStr = s[2];
  610 + String endTimeStr = s[3];
  611 + if (startTimeStr == null || endTimeStr == null || startTimeStr.length() != 14 || endTimeStr.length() != 14) {
  612 + defaultResult.setResult(HookResult.SUCCESS());
  613 + return defaultResult;
  614 + }
  615 + String startTime = DateUtil.urlToyyyy_MM_dd_HH_mm_ss(startTimeStr);
  616 + String endTime = DateUtil.urlToyyyy_MM_dd_HH_mm_ss(endTimeStr);
  617 + logger.info("[ZLM HOOK] 回放流未找到, 发起自动点播:{}->{}->{}/{}-{}-{}",
  618 + param.getMediaServerId(), param.getSchema(),
  619 + param.getApp(), param.getStream(),
  620 + startTime, endTime
  621 + );
  622 + RequestMessage msg = new RequestMessage();
  623 + String key = DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId;
  624 + boolean exist = resultHolder.exist(key, null);
  625 + msg.setKey(key);
  626 + String uuid = UUID.randomUUID().toString();
  627 + msg.setId(uuid);
  628 + DeferredResult<HookResult> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue());
  629 +
  630 + result.onTimeout(() -> {
  631 + logger.info("[ZLM HOOK] 回放流自动点播, 等待超时");
  632 + // 释放rtpserver
  633 + msg.setData(new HookResult(ErrorCode.ERROR100.getCode(), "点播超时"));
  634 + resultHolder.invokeResult(msg);
  635 + });
  636 +
  637 + resultHolder.put(key, uuid, result);
  638 +
  639 + if (!exist) {
  640 + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaInfo, param.getStream(), null,
  641 + device.isSsrcCheck(), true, 0, false, device.getStreamModeForParam());
  642 + playService.playBack(mediaInfo, ssrcInfo, deviceId, channelId, startTime, endTime, (code, message, data) -> {
  643 + msg.setData(new HookResult(code, message));
  644 + resultHolder.invokeResult(msg);
  645 + });
  646 + }
  647 + return result;
  648 + }else {
  649 + defaultResult.setResult(HookResult.SUCCESS());
  650 + return defaultResult;
603 651 }
604   - return result;
  652 +
605 653 } else {
606 654 // 拉流代理
607 655 StreamProxyItem streamProxyByAppAndStream = streamProxyService.getStreamProxyByAppAndStream(param.getApp(), param.getStream());
... ...
src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
... ... @@ -29,7 +29,6 @@ public interface IPlayService {
29 29  
30 30 void playBack(String deviceId, String channelId, String startTime, String endTime, ErrorCallback<Object> callback);
31 31 void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, ErrorCallback<Object> callback);
32   -
33 32 void zlmServerOffline(String mediaServerId);
34 33  
35 34 void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<Object> callback);
... ... @@ -44,4 +43,6 @@ public interface IPlayService {
44 43 void resumeRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException;
45 44  
46 45 void getSnap(String deviceId, String channelId, String fileName, ErrorCallback errorCallback);
  46 +
  47 +
47 48 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
... ... @@ -539,7 +539,19 @@ public class PlayServiceImpl implements IPlayService {
539 539 return;
540 540 }
541 541 MediaServerItem newMediaServerItem = getNewMediaServerItem(device);
542   - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, null, device.isSsrcCheck(), true, 0, false, device.getStreamModeForParam());
  542 + String stream = null;
  543 + if (newMediaServerItem.isRtpEnable()) {
  544 + String startTimeStr = startTime.replace("-", "")
  545 + .replace(":", "")
  546 + .replace(" ", "");
  547 + System.out.println(startTimeStr);
  548 + String endTimeTimeStr = endTime.replace("-", "")
  549 + .replace(":", "")
  550 + .replace(" ", "");
  551 + System.out.println(endTimeTimeStr);
  552 + stream = deviceId + "_" + channelId + "_" + startTimeStr + "_" + endTimeTimeStr;
  553 + }
  554 + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, stream, null, device.isSsrcCheck(), true, 0, false, device.getStreamModeForParam());
543 555 playBack(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, callback);
544 556 }
545 557  
... ...
src/main/java/com/genersoft/iot/vmp/utils/DateUtil.java
... ... @@ -53,6 +53,10 @@ public class DateUtil {
53 53 return formatter.format(formatterCompatibleISO8601.parse(formatTime));
54 54 }
55 55  
  56 + public static String urlToyyyy_MM_dd_HH_mm_ss(String formatTime) {
  57 + return formatter.format(urlFormatter.parse(formatTime));
  58 + }
  59 +
56 60 /**
57 61 * yyyy_MM_dd_HH_mm_ss 转时间戳
58 62 * @param formatTime
... ... @@ -82,6 +86,7 @@ public class DateUtil {
82 86 return urlFormatter.format(nowDateTime);
83 87 }
84 88  
  89 +
85 90 /**
86 91 * 格式校验
87 92 * @param timeStr 时间字符串
... ...