From 506f67cb0c1652447de3572cafde1e4184272fe9 Mon Sep 17 00:00:00 2001 From: shikong <919411476@qq.com> Date: Thu, 21 Sep 2023 00:49:46 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wvp/api/download/DownloadController.java | 10 +++ .../gb28181/Gb28181DownloadService.java | 87 ++++++++++++++++++- 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/gb28181-wvp-proxy-api/src/main/java/cn/skcks/docking/gb28181/wvp/api/download/DownloadController.java b/gb28181-wvp-proxy-api/src/main/java/cn/skcks/docking/gb28181/wvp/api/download/DownloadController.java index ea712c6..8829f99 100644 --- a/gb28181-wvp-proxy-api/src/main/java/cn/skcks/docking/gb28181/wvp/api/download/DownloadController.java +++ b/gb28181-wvp-proxy-api/src/main/java/cn/skcks/docking/gb28181/wvp/api/download/DownloadController.java @@ -1,12 +1,16 @@ package cn.skcks.docking.gb28181.wvp.api.download; +import cn.skcks.docking.gb28181.annotation.web.methods.GetJson; +import cn.skcks.docking.gb28181.wvp.api.video.dto.VideoReq; import cn.skcks.docking.gb28181.wvp.config.SwaggerConfig; import cn.skcks.docking.gb28181.wvp.service.download.DownloadService; +import cn.skcks.docking.gb28181.wvp.service.gb28181.Gb28181DownloadService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; +import org.springdoc.core.annotations.ParameterObject; import org.springdoc.core.models.GroupedOpenApi; import org.springframework.context.annotation.Bean; import org.springframework.web.bind.annotation.*; @@ -17,12 +21,18 @@ import org.springframework.web.bind.annotation.*; @RequestMapping("/download") public class DownloadController { private final DownloadService downloadService; + private final Gb28181DownloadService gb28181DownloadService; @Bean public GroupedOpenApi downloadApi() { return SwaggerConfig.api("DownloadApi", "/download"); } + @GetJson + public void download(@ParameterObject VideoReq req){ + gb28181DownloadService.download(req.getDeviceCode(),req.getStartTime(),req.getEndTime()); + } + @Operation(summary = "下载代理") @RequestMapping(method = RequestMethod.HEAD, value = "/proxy") public void downloadProxyHeader(HttpServletRequest request, HttpServletResponse response, @RequestParam String url) { diff --git a/gb28181-wvp-proxy-service/src/main/java/cn/skcks/docking/gb28181/wvp/service/gb28181/Gb28181DownloadService.java b/gb28181-wvp-proxy-service/src/main/java/cn/skcks/docking/gb28181/wvp/service/gb28181/Gb28181DownloadService.java index 1ecfc0a..e3f532f 100644 --- a/gb28181-wvp-proxy-service/src/main/java/cn/skcks/docking/gb28181/wvp/service/gb28181/Gb28181DownloadService.java +++ b/gb28181-wvp-proxy-service/src/main/java/cn/skcks/docking/gb28181/wvp/service/gb28181/Gb28181DownloadService.java @@ -1,16 +1,101 @@ package cn.skcks.docking.gb28181.wvp.service.gb28181; +import cn.skcks.docking.gb28181.core.sip.gb28181.sdp.GB28181Description; +import cn.skcks.docking.gb28181.core.sip.gb28181.sdp.MediaSdpHelper; +import cn.skcks.docking.gb28181.core.sip.gb28181.sdp.StreamMode; +import cn.skcks.docking.gb28181.media.config.ZlmMediaConfig; +import cn.skcks.docking.gb28181.media.dto.rtp.GetRtpInfoResp; +import cn.skcks.docking.gb28181.media.dto.rtp.OpenRtpServer; +import cn.skcks.docking.gb28181.media.dto.rtp.OpenRtpServerResp; +import cn.skcks.docking.gb28181.media.dto.status.ResponseStatus; +import cn.skcks.docking.gb28181.media.proxy.ZlmMediaService; +import cn.skcks.docking.gb28181.service.ssrc.SsrcService; +import cn.skcks.docking.gb28181.wvp.config.ProxySipConfig; +import cn.skcks.docking.gb28181.wvp.orm.mybatis.dynamic.model.WvpProxyDevice; +import cn.skcks.docking.gb28181.wvp.service.device.DeviceService; +import gov.nist.javax.sdp.fields.TimeField; import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; +import javax.sdp.Connection; +import javax.sdp.SdpFactory; +import javax.sdp.TimeDescription; +import javax.sip.ListeningPoint; import java.util.Date; +import java.util.List; +import java.util.Optional; +import java.util.Vector; @Slf4j @Service @RequiredArgsConstructor public class Gb28181DownloadService { - public void download(String deviceId, Date startTime, Date endTime){ + private final ZlmMediaService zlmMediaService; + private final ZlmMediaConfig zlmMediaConfig; + private final SsrcService ssrcService; + private final DeviceService deviceService; + private final ProxySipConfig proxySipConfig; + private String videoUrl(String streamId) { + return StringUtils.joinWith("/", zlmMediaConfig.getUrl(), "rtp", streamId + ".live.flv"); } + + private int openRtpServer(String streamId, int streamMode) { + GetRtpInfoResp rtpInfo = zlmMediaService.getRtpInfo(streamId); + if (rtpInfo.getExist()) { + log.warn("流 {} 已存在", streamId); + return 0; + } + + OpenRtpServer openRtpServer = new OpenRtpServer(); + openRtpServer.setPort(0); + openRtpServer.setStreamId(streamId); + openRtpServer.setTcpMode(streamMode); + OpenRtpServerResp openRtpServerResp = zlmMediaService.openRtpServer(openRtpServer); + log.info("openRtpServerResp => {}", openRtpServerResp); + if (!openRtpServerResp.getCode().equals(ResponseStatus.Success)) { + log.error("{}", openRtpServerResp.getCode().getMsg()); + return -1; + } + return openRtpServerResp.getPort(); + } + + public void download(String deviceCode, Date startTime, Date endTime){ + List deviceByDeviceCode = deviceService.getDeviceByDeviceCode(deviceCode); + if (deviceByDeviceCode.isEmpty()) { + log.info("未能找到 设备编码 为 {} 的设备",deviceCode); + } else { + WvpProxyDevice device = deviceByDeviceCode.get(0); + download(device.getGbDeviceId(), device.getGbDeviceChannelId(), startTime, endTime); + } + } + + @SneakyThrows + public void download(String gbDeviceId, String channel,Date startTime, Date endTime){ + Optional deviceByGbDeviceIdAndChannel = deviceService.getDeviceByGbDeviceIdAndChannel(gbDeviceId, channel); + if (deviceByGbDeviceIdAndChannel.isEmpty()) { + log.info("未能找到 编码 {}, 通道 {} 的设备", gbDeviceId, channel); + return ; + } + + long start = startTime.toInstant().getEpochSecond(); + long end = endTime.toInstant().getEpochSecond(); + String streamId = MediaSdpHelper.getStreamId(gbDeviceId, channel, String.valueOf(start), String.valueOf(end)); + int streamMode = proxySipConfig.getTransport().equalsIgnoreCase(ListeningPoint.UDP) ? 0 : 1; + String ip = zlmMediaConfig.getIp(); + int port = openRtpServer(streamId, streamMode); + String ssrc = ssrcService.getPlaySsrc(); + TimeField timeField = new TimeField(); + timeField.setStartTime(start); + timeField.setStopTime(end); + TimeDescription timeDescription = SdpFactory.getInstance().createTimeDescription(timeField); + GB28181Description gb28181Description = MediaSdpHelper.playback(gbDeviceId, channel, Connection.IP4, ip, port, ssrc, StreamMode.of(ListeningPoint.UDP), startTime, endTime); + gb28181Description.setSessionName(SdpFactory.getInstance().createSessionName(MediaSdpHelper.Action.DOWNLOAD.getAction())); + gb28181Description.setTimeDescriptions(new Vector<>(){{add(timeDescription);}}); + log.debug("{}", gb28181Description); + } + }