This commit is contained in:
shikong 2023-09-21 00:49:46 +08:00
parent e2aa0a5b0c
commit 506f67cb0c
2 changed files with 96 additions and 1 deletions

View File

@ -1,12 +1,16 @@
package cn.skcks.docking.gb28181.wvp.api.download; 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.config.SwaggerConfig;
import cn.skcks.docking.gb28181.wvp.service.download.DownloadService; 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.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springdoc.core.models.GroupedOpenApi; import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -17,12 +21,18 @@ import org.springframework.web.bind.annotation.*;
@RequestMapping("/download") @RequestMapping("/download")
public class DownloadController { public class DownloadController {
private final DownloadService downloadService; private final DownloadService downloadService;
private final Gb28181DownloadService gb28181DownloadService;
@Bean @Bean
public GroupedOpenApi downloadApi() { public GroupedOpenApi downloadApi() {
return SwaggerConfig.api("DownloadApi", "/download"); return SwaggerConfig.api("DownloadApi", "/download");
} }
@GetJson
public void download(@ParameterObject VideoReq req){
gb28181DownloadService.download(req.getDeviceCode(),req.getStartTime(),req.getEndTime());
}
@Operation(summary = "下载代理") @Operation(summary = "下载代理")
@RequestMapping(method = RequestMethod.HEAD, value = "/proxy") @RequestMapping(method = RequestMethod.HEAD, value = "/proxy")
public void downloadProxyHeader(HttpServletRequest request, HttpServletResponse response, @RequestParam String url) { public void downloadProxyHeader(HttpServletRequest request, HttpServletResponse response, @RequestParam String url) {

View File

@ -1,16 +1,101 @@
package cn.skcks.docking.gb28181.wvp.service.gb28181; 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.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; 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.Date;
import java.util.List;
import java.util.Optional;
import java.util.Vector;
@Slf4j @Slf4j
@Service @Service
@RequiredArgsConstructor @RequiredArgsConstructor
public class Gb28181DownloadService { 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<WvpProxyDevice> 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<WvpProxyDevice> 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);
}
} }