package com.dji.sample.manage.service.impl;
|
|
import com.dji.sample.component.live.FFMpeg;
|
import com.dji.sample.manage.model.dto.*;
|
import com.dji.sample.manage.model.param.DeviceQueryParam;
|
import com.dji.sample.manage.service.*;
|
import com.dji.sdk.cloudapi.device.DeviceDomainEnum;
|
import com.dji.sdk.cloudapi.device.VideoId;
|
import com.dji.sdk.cloudapi.livestream.*;
|
import com.dji.sdk.cloudapi.livestream.api.AbstractLivestreamService;
|
import com.dji.sdk.common.HttpResultResponse;
|
import com.dji.sdk.common.SDKManager;
|
import com.dji.sdk.mqtt.services.ServicesReplyData;
|
import com.dji.sdk.mqtt.services.TopicServicesResponse;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.util.List;
|
import java.util.Objects;
|
import java.util.Optional;
|
import java.util.stream.Collectors;
|
|
import static com.dji.sdk.cloudapi.livestream.LiveErrorCodeEnum.LIVE_STREAM_ALREADY_STARTED;
|
|
/**
|
* @author sean.zhou
|
* @version 0.1
|
* @date 2021/11/22
|
*/
|
@Service
|
@Transactional
|
public class LiveStreamServiceImpl implements ILiveStreamService {
|
|
@Autowired
|
private ICapacityCameraService capacityCameraService;
|
|
@Autowired
|
private IDeviceService deviceService;
|
|
@Autowired
|
private IWorkspaceService workspaceService;
|
|
@Autowired
|
private IDeviceRedisService deviceRedisService;
|
|
@Autowired
|
private AbstractLivestreamService abstractLivestreamService;
|
|
@Override
|
public List<CapacityDeviceDTO> getLiveCapacity(String workspaceId) {
|
|
// Query all devices in this workspace.
|
List<DeviceDTO> devicesList = deviceService.getDevicesByParams(
|
DeviceQueryParam.builder()
|
.workspaceId(workspaceId)
|
.domains(List.of(DeviceDomainEnum.DRONE.getDomain(), DeviceDomainEnum.DOCK.getDomain()))
|
.build());
|
|
// Query the live capability of each drone.
|
return devicesList.stream()
|
.filter(device -> deviceRedisService.checkDeviceOnline(device.getDeviceSn()))
|
.map(device -> CapacityDeviceDTO.builder()
|
.name(Objects.requireNonNullElse(device.getNickname(), device.getDeviceName()))
|
.sn(device.getDeviceSn())
|
.camerasList(capacityCameraService.getCapacityCameraByDeviceSn(device.getDeviceSn()))
|
.build())
|
.collect(Collectors.toList());
|
}
|
|
@Override
|
public HttpResultResponse liveStart(LiveTypeDTO liveParam) {
|
// Check if this lens is available live.
|
// String playUrl = "rtmp://111.40.46.199:1622/push/9";
|
HttpResultResponse<DeviceDTO> responseResult = this.checkBeforeLive(liveParam.getVideoId());
|
if (HttpResultResponse.CODE_SUCCESS != responseResult.getCode()) {
|
return responseResult;
|
}
|
|
// ILivestreamUrl url = LiveStreamProperty.get(liveParam.getUrlType());
|
// url = setExt(liveParam.getUrlType(), url, liveParam.getVideoId());
|
LivestreamRtmpUrl rtmpUrl = new LivestreamRtmpUrl();
|
rtmpUrl.setUrl(liveParam.getUrl());
|
LivestreamWhipUrl webrtcUrl = new LivestreamWhipUrl();
|
webrtcUrl.setUrl(liveParam.getUrl());
|
|
TopicServicesResponse<ServicesReplyData<String>> response = abstractLivestreamService.liveStartPush(
|
SDKManager.getDeviceSDK(responseResult.getData().getDeviceSn()),
|
new LiveStartPushRequest()
|
.setUrl(rtmpUrl)
|
// .setUrl(webrtcUrl)
|
.setUrlType(liveParam.getUrlType())
|
.setVideoId(liveParam.getVideoId())
|
.setVideoQuality(liveParam.getVideoQuality()));
|
|
if (!response.getData().getResult().isSuccess() && !response.getData().getResult().toString().contains(LIVE_STREAM_ALREADY_STARTED.getCode().toString())) {
|
return HttpResultResponse.error(response.getData().getResult());
|
}
|
|
LiveDTO live = new LiveDTO();
|
live.setUrl(liveParam.getUrl().replace("rtmp", "http").replace("1630", "1629").replace("/live",""));
|
|
|
|
return HttpResultResponse.success(live);
|
}
|
|
@Override
|
public HttpResultResponse liveStop(VideoId videoId) {
|
HttpResultResponse<DeviceDTO> responseResult = this.checkBeforeLive(videoId);
|
if (HttpResultResponse.CODE_SUCCESS != responseResult.getCode()) {
|
return responseResult;
|
}
|
|
TopicServicesResponse<ServicesReplyData> response = abstractLivestreamService.liveStopPush(
|
SDKManager.getDeviceSDK(responseResult.getData().getDeviceSn()), new LiveStopPushRequest()
|
.setVideoId(videoId));
|
if (!response.getData().getResult().isSuccess()) {
|
return HttpResultResponse.error(response.getData().getResult());
|
}
|
|
return HttpResultResponse.success();
|
}
|
|
@Override
|
public HttpResultResponse liveSetQuality(LiveTypeDTO liveParam) {
|
HttpResultResponse<DeviceDTO> responseResult = this.checkBeforeLive(liveParam.getVideoId());
|
if (responseResult.getCode() != 0) {
|
return responseResult;
|
}
|
|
TopicServicesResponse<ServicesReplyData> response = abstractLivestreamService.liveSetQuality(
|
SDKManager.getDeviceSDK(responseResult.getData().getDeviceSn()), new LiveSetQualityRequest()
|
.setVideoQuality(liveParam.getVideoQuality())
|
.setVideoId(liveParam.getVideoId()));
|
if (!response.getData().getResult().isSuccess()) {
|
return HttpResultResponse.error(response.getData().getResult());
|
}
|
|
return HttpResultResponse.success();
|
}
|
|
@Override
|
public HttpResultResponse liveLensChange(LiveTypeDTO liveParam) {
|
HttpResultResponse<DeviceDTO> responseResult = this.checkBeforeLive(liveParam.getVideoId());
|
if (HttpResultResponse.CODE_SUCCESS != responseResult.getCode()) {
|
return responseResult;
|
}
|
|
TopicServicesResponse<ServicesReplyData> response = abstractLivestreamService.liveLensChange(
|
SDKManager.getDeviceSDK(responseResult.getData().getDeviceSn()), new LiveLensChangeRequest()
|
.setVideoType(liveParam.getVideoType())
|
.setVideoId(liveParam.getVideoId()));
|
|
if (!response.getData().getResult().isSuccess()) {
|
return HttpResultResponse.error(response.getData().getResult());
|
}
|
|
return HttpResultResponse.success();
|
}
|
|
/**
|
* Check if this lens is available live.
|
*
|
* @param videoId
|
* @return
|
*/
|
private HttpResultResponse<DeviceDTO> checkBeforeLive(VideoId videoId) {
|
if (Objects.isNull(videoId)) {
|
return HttpResultResponse.error(LiveErrorCodeEnum.ERROR_PARAMETERS);
|
}
|
|
Optional<DeviceDTO> deviceOpt = deviceService.getDeviceBySn(videoId.getDroneSn());
|
// Check if the gateway device connected to this drone exists
|
if (deviceOpt.isEmpty()) {
|
return HttpResultResponse.error(LiveErrorCodeEnum.NO_AIRCRAFT);
|
}
|
|
if (DeviceDomainEnum.DOCK == deviceOpt.get().getDomain()) {
|
return HttpResultResponse.success(deviceOpt.get());
|
}
|
List<DeviceDTO> gatewayList = deviceService.getDevicesByParams(
|
DeviceQueryParam.builder()
|
.childSn(videoId.getDroneSn())
|
.build());
|
if (gatewayList.isEmpty()) {
|
return HttpResultResponse.error(LiveErrorCodeEnum.NO_FLIGHT_CONTROL);
|
}
|
|
return HttpResultResponse.success(gatewayList.get(0));
|
}
|
|
/**
|
* This is business-customized logic and is only used for testing.
|
*
|
* @param type
|
* @param url
|
* @param videoId
|
*/
|
private ILivestreamUrl setExt(UrlTypeEnum type, ILivestreamUrl url, VideoId videoId) {
|
switch (type) {
|
case AGORA:
|
LivestreamAgoraUrl agoraUrl = (LivestreamAgoraUrl) url.clone();
|
return agoraUrl.setSn(videoId.getDroneSn());
|
case RTMP:
|
// LivestreamRtmpUrl rtmpUrl = (LivestreamRtmpUrl) url;
|
// return rtmpUrl.setUrl(rtmpUrl.getUrl() + videoId.getDroneSn() + "-" + videoId.getPayloadIndex().toString());
|
LivestreamRtmpUrl rtmpUrl = new LivestreamRtmpUrl();
|
return rtmpUrl.setUrl(rtmpUrl.getUrl() + videoId.getDroneSn() + "-" + videoId.getPayloadIndex().toString());
|
case GB28181:
|
String random = String.valueOf(Math.abs(videoId.getDroneSn().hashCode()) % 1000);
|
LivestreamGb28181Url gbUrl = (LivestreamGb28181Url) url.clone();
|
gbUrl.setAgentID(gbUrl.getAgentID().substring(0, 20 - random.length()) + random);
|
String deviceType = String.valueOf(videoId.getPayloadIndex().getType().getType());
|
return gbUrl.setChannel(gbUrl.getChannel().substring(0, 20 - deviceType.length()) + deviceType);
|
case WHIP:
|
LivestreamWhipUrl whipUrl = (LivestreamWhipUrl) url.clone();
|
return whipUrl.setUrl(whipUrl.getUrl() + videoId.getDroneSn() + "-" + videoId.getPayloadIndex().toString());
|
}
|
return url;
|
}
|
}
|