Commit 59d8f2f9152b3c3106abae64bef343cde842f225
1 parent
51634b1b
支持录像回放使用固定流地址以及自动点播录像回放
Showing
7 changed files
with
97 additions
and
28 deletions
sql/2.6.9更新.sql
0 → 100644
sql/初始化.sql
| @@ -79,7 +79,7 @@ create table wvp_device_channel ( | @@ -79,7 +79,7 @@ create table wvp_device_channel ( | ||
| 79 | custom_longitude double precision, | 79 | custom_longitude double precision, |
| 80 | latitude double precision, | 80 | latitude double precision, |
| 81 | custom_latitude double precision, | 81 | custom_latitude double precision, |
| 82 | - stream_id character varying(50), | 82 | + stream_id character varying(255), |
| 83 | device_id character varying(50) not null, | 83 | device_id character varying(50) not null, |
| 84 | parental character varying(50), | 84 | parental character varying(50), |
| 85 | has_audio bool default false, | 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,6 +59,7 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp | ||
| 59 | // 未注册的设备不做处理 | 59 | // 未注册的设备不做处理 |
| 60 | return; | 60 | return; |
| 61 | } | 61 | } |
| 62 | + logger.info("[收到心跳], device: {}", device.getDeviceId()); | ||
| 62 | SIPRequest request = (SIPRequest) evt.getRequest(); | 63 | SIPRequest request = (SIPRequest) evt.getRequest(); |
| 63 | // 回复200 OK | 64 | // 回复200 OK |
| 64 | try { | 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,8 +24,10 @@ import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; | ||
| 24 | import com.genersoft.iot.vmp.media.zlm.dto.hook.*; | 24 | import com.genersoft.iot.vmp.media.zlm.dto.hook.*; |
| 25 | import com.genersoft.iot.vmp.service.*; | 25 | import com.genersoft.iot.vmp.service.*; |
| 26 | import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; | 26 | import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; |
| 27 | +import com.genersoft.iot.vmp.service.bean.SSRCInfo; | ||
| 27 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | 28 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 28 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | 29 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 30 | +import com.genersoft.iot.vmp.utils.DateUtil; | ||
| 29 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; | 31 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; |
| 30 | import com.genersoft.iot.vmp.vmanager.bean.OtherRtpSendInfo; | 32 | import com.genersoft.iot.vmp.vmanager.bean.OtherRtpSendInfo; |
| 31 | import com.genersoft.iot.vmp.vmanager.bean.StreamContent; | 33 | import com.genersoft.iot.vmp.vmanager.bean.StreamContent; |
| @@ -559,7 +561,7 @@ public class ZLMHttpHookListener { | @@ -559,7 +561,7 @@ public class ZLMHttpHookListener { | ||
| 559 | 561 | ||
| 560 | if ("rtp".equals(param.getApp())) { | 562 | if ("rtp".equals(param.getApp())) { |
| 561 | String[] s = param.getStream().split("_"); | 563 | String[] s = param.getStream().split("_"); |
| 562 | - if (!mediaInfo.isRtpEnable() || s.length != 2) { | 564 | + if (!mediaInfo.isRtpEnable() || (s.length != 2 && s.length != 4)) { |
| 563 | defaultResult.setResult(HookResult.SUCCESS()); | 565 | defaultResult.setResult(HookResult.SUCCESS()); |
| 564 | return defaultResult; | 566 | return defaultResult; |
| 565 | } | 567 | } |
| @@ -575,33 +577,79 @@ public class ZLMHttpHookListener { | @@ -575,33 +577,79 @@ public class ZLMHttpHookListener { | ||
| 575 | defaultResult.setResult(new HookResult(ErrorCode.ERROR404.getCode(), ErrorCode.ERROR404.getMsg())); | 577 | defaultResult.setResult(new HookResult(ErrorCode.ERROR404.getCode(), ErrorCode.ERROR404.getMsg())); |
| 576 | return defaultResult; | 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 | resultHolder.invokeResult(msg); | 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 | } else { | 653 | } else { |
| 606 | // 拉流代理 | 654 | // 拉流代理 |
| 607 | StreamProxyItem streamProxyByAppAndStream = streamProxyService.getStreamProxyByAppAndStream(param.getApp(), param.getStream()); | 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,7 +29,6 @@ public interface IPlayService { | ||
| 29 | 29 | ||
| 30 | void playBack(String deviceId, String channelId, String startTime, String endTime, ErrorCallback<Object> callback); | 30 | void playBack(String deviceId, String channelId, String startTime, String endTime, ErrorCallback<Object> callback); |
| 31 | void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, ErrorCallback<Object> callback); | 31 | void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, ErrorCallback<Object> callback); |
| 32 | - | ||
| 33 | void zlmServerOffline(String mediaServerId); | 32 | void zlmServerOffline(String mediaServerId); |
| 34 | 33 | ||
| 35 | void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<Object> callback); | 34 | void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<Object> callback); |
| @@ -44,4 +43,6 @@ public interface IPlayService { | @@ -44,4 +43,6 @@ public interface IPlayService { | ||
| 44 | void resumeRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException; | 43 | void resumeRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException; |
| 45 | 44 | ||
| 46 | void getSnap(String deviceId, String channelId, String fileName, ErrorCallback errorCallback); | 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,7 +539,19 @@ public class PlayServiceImpl implements IPlayService { | ||
| 539 | return; | 539 | return; |
| 540 | } | 540 | } |
| 541 | MediaServerItem newMediaServerItem = getNewMediaServerItem(device); | 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 | playBack(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, callback); | 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,6 +53,10 @@ public class DateUtil { | ||
| 53 | return formatter.format(formatterCompatibleISO8601.parse(formatTime)); | 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 | * yyyy_MM_dd_HH_mm_ss 转时间戳 | 61 | * yyyy_MM_dd_HH_mm_ss 转时间戳 |
| 58 | * @param formatTime | 62 | * @param formatTime |
| @@ -82,6 +86,7 @@ public class DateUtil { | @@ -82,6 +86,7 @@ public class DateUtil { | ||
| 82 | return urlFormatter.format(nowDateTime); | 86 | return urlFormatter.format(nowDateTime); |
| 83 | } | 87 | } |
| 84 | 88 | ||
| 89 | + | ||
| 85 | /** | 90 | /** |
| 86 | * 格式校验 | 91 | * 格式校验 |
| 87 | * @param timeStr 时间字符串 | 92 | * @param timeStr 时间字符串 |