修复国标视频点播三种点播方式(自动点播,上级点播,接口点播)并发情况下失败的问题
This commit is contained in:
@@ -1,7 +1,11 @@
|
||||
package com.genersoft.iot.vmp.vmanager.gb28181.play;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.genersoft.iot.vmp.common.InviteInfo;
|
||||
import com.genersoft.iot.vmp.common.InviteSessionStatus;
|
||||
import com.genersoft.iot.vmp.common.InviteSessionType;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
@@ -14,12 +18,13 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.service.IInviteStreamService;
|
||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.service.IMediaService;
|
||||
import com.genersoft.iot.vmp.service.IPlayService;
|
||||
import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.DeferredResultEx;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.StreamContent;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
|
||||
@@ -59,6 +64,9 @@ public class PlayController {
|
||||
@Autowired
|
||||
private IRedisCatchStorage redisCatchStorage;
|
||||
|
||||
@Autowired
|
||||
private IInviteStreamService inviteStreamService;
|
||||
|
||||
@Autowired
|
||||
private ZLMRESTfulUtils zlmresTfulUtils;
|
||||
|
||||
@@ -88,14 +96,12 @@ public class PlayController {
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
|
||||
|
||||
RequestMessage msg = new RequestMessage();
|
||||
RequestMessage requestMessage = new RequestMessage();
|
||||
String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId;
|
||||
boolean exist = resultHolder.exist(key, null);
|
||||
msg.setKey(key);
|
||||
requestMessage.setKey(key);
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
msg.setId(uuid);
|
||||
requestMessage.setId(uuid);
|
||||
DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue());
|
||||
DeferredResultEx<WVPResult<StreamContent>> deferredResultEx = new DeferredResultEx<>(result);
|
||||
|
||||
result.onTimeout(()->{
|
||||
logger.info("点播接口等待超时");
|
||||
@@ -103,32 +109,36 @@ public class PlayController {
|
||||
WVPResult<StreamInfo> wvpResult = new WVPResult<>();
|
||||
wvpResult.setCode(ErrorCode.ERROR100.getCode());
|
||||
wvpResult.setMsg("点播超时");
|
||||
msg.setData(wvpResult);
|
||||
resultHolder.invokeResult(msg);
|
||||
requestMessage.setData(wvpResult);
|
||||
resultHolder.invokeResult(requestMessage);
|
||||
});
|
||||
// TODO 在点播未成功的情况下在此调用接口点播会导致返回的流地址ip错误
|
||||
deferredResultEx.setFilter(result1 -> {
|
||||
WVPResult<StreamInfo> wvpResult1 = (WVPResult<StreamInfo>)result1;
|
||||
WVPResult<StreamContent> resultStream = new WVPResult<>();
|
||||
resultStream.setCode(wvpResult1.getCode());
|
||||
resultStream.setMsg(wvpResult1.getMsg());
|
||||
if (wvpResult1.getCode() == ErrorCode.SUCCESS.getCode()) {
|
||||
StreamInfo data = wvpResult1.getData().clone();
|
||||
if (userSetting.getUseSourceIpAsStreamIp()) {
|
||||
data.channgeStreamIp(request.getLocalName());
|
||||
}
|
||||
resultStream.setData(new StreamContent(wvpResult1.getData()));
|
||||
}
|
||||
return resultStream;
|
||||
});
|
||||
|
||||
|
||||
// 录像查询以channelId作为deviceId查询
|
||||
resultHolder.put(key, uuid, deferredResultEx);
|
||||
resultHolder.put(key, uuid, result);
|
||||
|
||||
if (!exist) {
|
||||
playService.play(newMediaServerItem, deviceId, channelId, null, null, null);
|
||||
}
|
||||
playService.play(newMediaServerItem, deviceId, channelId, ((code, msg, data) -> {
|
||||
System.out.println("controller收到回调");
|
||||
System.out.println(JSON.toJSONString(data));
|
||||
WVPResult<StreamContent> wvpResult = new WVPResult<>();
|
||||
if (code == InviteErrorCode.SUCCESS.getCode()) {
|
||||
wvpResult.setCode(ErrorCode.SUCCESS.getCode());
|
||||
wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());
|
||||
|
||||
if (data != null) {
|
||||
StreamInfo streamInfo = (StreamInfo)data;
|
||||
if (userSetting.getUseSourceIpAsStreamIp()) {
|
||||
streamInfo.channgeStreamIp(request.getLocalName());
|
||||
}
|
||||
wvpResult.setData(new StreamContent(streamInfo));
|
||||
}
|
||||
}else {
|
||||
wvpResult.setCode(code);
|
||||
wvpResult.setMsg(msg);
|
||||
}
|
||||
System.out.println(JSON.toJSONString(wvpResult));
|
||||
requestMessage.setData(wvpResult);
|
||||
resultHolder.invokeResult(requestMessage);
|
||||
}));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -149,21 +159,22 @@ public class PlayController {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备[" + deviceId + "]不存在");
|
||||
}
|
||||
|
||||
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
|
||||
if (streamInfo == null) {
|
||||
InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId);
|
||||
if (inviteInfo == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "点播未找到");
|
||||
}
|
||||
|
||||
try {
|
||||
logger.warn("[停止点播] {}/{}", device.getDeviceId(), channelId);
|
||||
cmder.streamByeCmd(device, channelId, streamInfo.getStream(), null, null);
|
||||
} catch (InvalidArgumentException | SipException | ParseException | SsrcTransactionNotFoundException e) {
|
||||
logger.error("[命令发送失败] 停止点播, 发送BYE: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
if (InviteSessionStatus.ok == inviteInfo.getStatus()) {
|
||||
try {
|
||||
logger.warn("[停止点播] {}/{}", device.getDeviceId(), channelId);
|
||||
cmder.streamByeCmd(device, channelId, inviteInfo.getStream(), null, null);
|
||||
} catch (InvalidArgumentException | SipException | ParseException | SsrcTransactionNotFoundException e) {
|
||||
logger.error("[命令发送失败] 停止点播, 发送BYE: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
redisCatchStorage.stopPlay(streamInfo);
|
||||
inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId);
|
||||
|
||||
storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
|
||||
storager.stopPlay(deviceId, channelId);
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("deviceId", deviceId);
|
||||
json.put("channelId", channelId);
|
||||
@@ -178,15 +189,14 @@ public class PlayController {
|
||||
@Parameter(name = "streamId", description = "视频流ID", required = true)
|
||||
@PostMapping("/convert/{streamId}")
|
||||
public JSONObject playConvert(@PathVariable String streamId) {
|
||||
StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId);
|
||||
if (streamInfo == null) {
|
||||
streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);
|
||||
}
|
||||
if (streamInfo == null) {
|
||||
// StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId);
|
||||
|
||||
InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, streamId);
|
||||
if (inviteInfo == null || inviteInfo.getStreamInfo() == null) {
|
||||
logger.warn("视频转码API调用失败!, 视频流已经停止!");
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到视频流信息, 视频流可能已经停止");
|
||||
}
|
||||
MediaServerItem mediaInfo = mediaServerService.getOne(streamInfo.getMediaServerId());
|
||||
MediaServerItem mediaInfo = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId());
|
||||
JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId);
|
||||
if (!rtpInfo.getBoolean("exist")) {
|
||||
logger.warn("视频转码API调用失败!, 视频流已停止推流!");
|
||||
|
||||
Reference in New Issue
Block a user