完成向上级联->点播--002
parent
e09e541c82
commit
1b44ba3367
|
@ -15,6 +15,7 @@ import com.alibaba.fastjson.JSON;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.response.impl.*;
|
import com.genersoft.iot.vmp.gb28181.transmit.response.impl.*;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.response.impl.*;
|
import com.genersoft.iot.vmp.gb28181.transmit.response.impl.*;
|
||||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
|
import com.genersoft.iot.vmp.vmanager.service.IPlayService;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
@ -103,6 +104,9 @@ public class SIPProcessorFactory {
|
||||||
@Autowired
|
@Autowired
|
||||||
private OtherResponseProcessor otherResponseProcessor;
|
private OtherResponseProcessor otherResponseProcessor;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IPlayService playService;
|
||||||
|
|
||||||
|
|
||||||
// 注:这里使用注解会导致循环依赖注入,暂用springBean
|
// 注:这里使用注解会导致循环依赖注入,暂用springBean
|
||||||
private SipProvider tcpSipProvider;
|
private SipProvider tcpSipProvider;
|
||||||
|
@ -120,7 +124,9 @@ public class SIPProcessorFactory {
|
||||||
processor.setTcpSipProvider(getTcpSipProvider());
|
processor.setTcpSipProvider(getTcpSipProvider());
|
||||||
processor.setUdpSipProvider(getUdpSipProvider());
|
processor.setUdpSipProvider(getUdpSipProvider());
|
||||||
|
|
||||||
|
processor.setCmder(cmder);
|
||||||
processor.setCmderFroPlatform(cmderFroPlatform);
|
processor.setCmderFroPlatform(cmderFroPlatform);
|
||||||
|
processor.setPlayService(playService);
|
||||||
processor.setStorager(storager);
|
processor.setStorager(storager);
|
||||||
return processor;
|
return processor;
|
||||||
} else if (Request.REGISTER.equals(method)) {
|
} else if (Request.REGISTER.equals(method)) {
|
||||||
|
|
|
@ -10,19 +10,26 @@ import javax.sip.header.SubjectHeader;
|
||||||
import javax.sip.message.Request;
|
import javax.sip.message.Request;
|
||||||
import javax.sip.message.Response;
|
import javax.sip.message.Response;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||||
import com.genersoft.iot.vmp.gb28181.sdp.Codec;
|
import com.genersoft.iot.vmp.gb28181.sdp.Codec;
|
||||||
import com.genersoft.iot.vmp.gb28181.sdp.MediaDescription;
|
import com.genersoft.iot.vmp.gb28181.sdp.MediaDescription;
|
||||||
import com.genersoft.iot.vmp.gb28181.sdp.SdpParser;
|
import com.genersoft.iot.vmp.gb28181.sdp.SdpParser;
|
||||||
import com.genersoft.iot.vmp.gb28181.sdp.SessionDescription;
|
import com.genersoft.iot.vmp.gb28181.sdp.SessionDescription;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
|
import com.genersoft.iot.vmp.vmanager.play.bean.PlayResult;
|
||||||
|
import com.genersoft.iot.vmp.vmanager.service.IPlayService;
|
||||||
import gov.nist.javax.sip.address.AddressImpl;
|
import gov.nist.javax.sip.address.AddressImpl;
|
||||||
import gov.nist.javax.sip.address.SipUri;
|
import gov.nist.javax.sip.address.SipUri;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
|
@ -41,6 +48,10 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
||||||
|
|
||||||
private IVideoManagerStorager storager;
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
|
private SIPCommander cmder;
|
||||||
|
|
||||||
|
private IPlayService playService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理invite请求
|
* 处理invite请求
|
||||||
*
|
*
|
||||||
|
@ -119,7 +130,30 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
||||||
|
|
||||||
|
|
||||||
String ssrc = sdp.getSsrc();
|
String ssrc = sdp.getSsrc();
|
||||||
|
|
||||||
|
Device device = storager.queryVideoDeviceByPlatformIdAndChannelId(platformId, channelId);
|
||||||
|
if (device == null) {
|
||||||
|
logger.warn("点播平台{}的通道{}时未找到设备信息", platformId, channel);
|
||||||
|
response500Ack(evt);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 通知下级推流,
|
// 通知下级推流,
|
||||||
|
PlayResult playResult = playService.play(device.getDeviceId(), channelId, (response)->{
|
||||||
|
// 收到推流, 回复200OK
|
||||||
|
|
||||||
|
},(event -> {
|
||||||
|
// 未知错误。直接转发设备点播的错误
|
||||||
|
Response response = null;
|
||||||
|
try {
|
||||||
|
response = getMessageFactory().createResponse(event.getResponse().getStatusCode(), evt.getRequest());
|
||||||
|
getServerTransaction(evt).sendResponse(response);
|
||||||
|
|
||||||
|
} catch (ParseException | SipException | InvalidArgumentException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
playResult.getResult();
|
||||||
// 查找合适的端口推流,
|
// 查找合适的端口推流,
|
||||||
// 发送 200ok
|
// 发送 200ok
|
||||||
// 收到ack后调用推流接口
|
// 收到ack后调用推流接口
|
||||||
|
@ -149,14 +183,16 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* 回复404
|
* 回复200 OK
|
||||||
* @param evt
|
* @param evt
|
||||||
* @throws SipException
|
* @throws SipException
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
* @throws ParseException
|
* @throws ParseException
|
||||||
*/
|
*/
|
||||||
private void response404Ack(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException {
|
private void responseAck(RequestEvent evt, String sdp) throws SipException, InvalidArgumentException, ParseException {
|
||||||
Response response = getMessageFactory().createResponse(Response.NOT_FOUND, evt.getRequest());
|
Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
|
||||||
|
ContentTypeHeader contentTypeHeader = getHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
|
||||||
|
response.setContent(sdp, contentTypeHeader);
|
||||||
getServerTransaction(evt).sendResponse(response);
|
getServerTransaction(evt).sendResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,6 +208,18 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
||||||
getServerTransaction(evt).sendResponse(response);
|
getServerTransaction(evt).sendResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* 回复404
|
||||||
|
* @param evt
|
||||||
|
* @throws SipException
|
||||||
|
* @throws InvalidArgumentException
|
||||||
|
* @throws ParseException
|
||||||
|
*/
|
||||||
|
private void response404Ack(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException {
|
||||||
|
Response response = getMessageFactory().createResponse(Response.NOT_FOUND, evt.getRequest());
|
||||||
|
getServerTransaction(evt).sendResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* 回复488
|
* 回复488
|
||||||
* @param evt
|
* @param evt
|
||||||
|
@ -185,16 +233,14 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* 回复200 OK
|
* 回复500
|
||||||
* @param evt
|
* @param evt
|
||||||
* @throws SipException
|
* @throws SipException
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
* @throws ParseException
|
* @throws ParseException
|
||||||
*/
|
*/
|
||||||
private void responseAck(RequestEvent evt, String sdp) throws SipException, InvalidArgumentException, ParseException {
|
private void response500Ack(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException {
|
||||||
Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
|
Response response = getMessageFactory().createResponse(Response.SERVER_INTERNAL_ERROR, evt.getRequest());
|
||||||
ContentTypeHeader contentTypeHeader = getHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
|
|
||||||
response.setContent(sdp, contentTypeHeader);
|
|
||||||
getServerTransaction(evt).sendResponse(response);
|
getServerTransaction(evt).sendResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,6 +253,8 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public SIPCommanderFroPlatform getCmderFroPlatform() {
|
public SIPCommanderFroPlatform getCmderFroPlatform() {
|
||||||
return cmderFroPlatform;
|
return cmderFroPlatform;
|
||||||
}
|
}
|
||||||
|
@ -222,4 +270,20 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
|
||||||
public void setStorager(IVideoManagerStorager storager) {
|
public void setStorager(IVideoManagerStorager storager) {
|
||||||
this.storager = storager;
|
this.storager = storager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SIPCommander getCmder() {
|
||||||
|
return cmder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCmder(SIPCommander cmder) {
|
||||||
|
this.cmder = cmder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IPlayService getPlayService() {
|
||||||
|
return playService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlayService(IPlayService playService) {
|
||||||
|
this.playService = playService;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -234,4 +234,6 @@ public interface IVideoManagerStorager {
|
||||||
|
|
||||||
|
|
||||||
DeviceChannel queryChannelInParentPlatform(String platformId, String channelId);
|
DeviceChannel queryChannelInParentPlatform(String platformId, String channelId);
|
||||||
|
|
||||||
|
Device queryVideoDeviceByPlatformIdAndChannelId(String platformId, String channelId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -335,4 +335,9 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
|
||||||
DeviceChannel channel = patformChannelMapper.queryChannelInParentPlatform(platformId, channelId);
|
DeviceChannel channel = patformChannelMapper.queryChannelInParentPlatform(platformId, channelId);
|
||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Device queryVideoDeviceByPlatformIdAndChannelId(String platformId, String channelId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
|
import com.genersoft.iot.vmp.vmanager.play.bean.PlayResult;
|
||||||
import com.genersoft.iot.vmp.vmanager.service.IPlayService;
|
import com.genersoft.iot.vmp.vmanager.service.IPlayService;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -64,62 +65,19 @@ public class PlayController {
|
||||||
@PathVariable String channelId) {
|
@PathVariable String channelId) {
|
||||||
|
|
||||||
|
|
||||||
Device device = storager.queryVideoDevice(deviceId);
|
PlayResult playResult = playService.play(deviceId, channelId, null, null);
|
||||||
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
|
|
||||||
|
|
||||||
UUID uuid = UUID.randomUUID();
|
|
||||||
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>();
|
|
||||||
|
|
||||||
// 录像查询以channelId作为deviceId查询
|
|
||||||
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result);
|
|
||||||
|
|
||||||
if (streamInfo == null) {
|
|
||||||
// 发送点播消息
|
|
||||||
cmder.playStreamCmd(device, channelId, (JSONObject response) -> {
|
|
||||||
logger.info("收到订阅消息: " + response.toJSONString());
|
|
||||||
playService.onPublishHandlerForPlay(response, deviceId, channelId, uuid.toString());
|
|
||||||
}, event -> {
|
|
||||||
RequestMessage msg = new RequestMessage();
|
|
||||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
|
|
||||||
Response response = event.getResponse();
|
|
||||||
msg.setData(String.format("点播失败, 错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
|
|
||||||
resultHolder.invokeResult(msg);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
String streamId = streamInfo.getStreamId();
|
|
||||||
JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId);
|
|
||||||
if (rtpInfo.getBoolean("exist")) {
|
|
||||||
RequestMessage msg = new RequestMessage();
|
|
||||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
|
|
||||||
msg.setData(JSON.toJSONString(streamInfo));
|
|
||||||
resultHolder.invokeResult(msg);
|
|
||||||
} else {
|
|
||||||
redisCatchStorage.stopPlay(streamInfo);
|
|
||||||
storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
|
|
||||||
cmder.playStreamCmd(device, channelId, (JSONObject response) -> {
|
|
||||||
logger.info("收到订阅消息: " + response.toJSONString());
|
|
||||||
playService.onPublishHandlerForPlay(response, deviceId, channelId, uuid.toString());
|
|
||||||
}, event -> {
|
|
||||||
RequestMessage msg = new RequestMessage();
|
|
||||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
|
|
||||||
Response response = event.getResponse();
|
|
||||||
msg.setData(String.format("点播失败, 错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
|
|
||||||
resultHolder.invokeResult(msg);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 超时处理
|
// 超时处理
|
||||||
result.onTimeout(()->{
|
playResult.getResult().onTimeout(()->{
|
||||||
logger.warn(String.format("设备点播超时,deviceId:%s ,channelId:%s", deviceId, channelId));
|
logger.warn(String.format("设备点播超时,deviceId:%s ,channelId:%s", deviceId, channelId));
|
||||||
// 释放rtpserver
|
// 释放rtpserver
|
||||||
cmder.closeRTPServer(device, channelId);
|
cmder.closeRTPServer(playResult.getDevice(), channelId);
|
||||||
RequestMessage msg = new RequestMessage();
|
RequestMessage msg = new RequestMessage();
|
||||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
|
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + playResult.getUuid());
|
||||||
msg.setData("Timeout");
|
msg.setData("Timeout");
|
||||||
resultHolder.invokeResult(msg);
|
resultHolder.invokeResult(msg);
|
||||||
});
|
});
|
||||||
return result;
|
return playResult.getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/play/{streamId}/stop")
|
@PostMapping("/play/{streamId}/stop")
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
package com.genersoft.iot.vmp.vmanager.play.bean;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.context.request.async.DeferredResult;
|
||||||
|
|
||||||
|
public class PlayResult {
|
||||||
|
|
||||||
|
private DeferredResult<ResponseEntity<String>> result;
|
||||||
|
private String uuid;
|
||||||
|
|
||||||
|
private Device device;
|
||||||
|
|
||||||
|
public DeferredResult<ResponseEntity<String>> getResult() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResult(DeferredResult<ResponseEntity<String>> result) {
|
||||||
|
this.result = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUuid() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUuid(String uuid) {
|
||||||
|
this.uuid = uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Device getDevice() {
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDevice(Device device) {
|
||||||
|
this.device = device;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,11 @@ package com.genersoft.iot.vmp.vmanager.service;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
|
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
|
||||||
|
import com.genersoft.iot.vmp.vmanager.play.bean.PlayResult;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.context.request.async.DeferredResult;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 点播处理
|
* 点播处理
|
||||||
|
@ -10,4 +15,6 @@ public interface IPlayService {
|
||||||
|
|
||||||
void onPublishHandlerForPlayBack(JSONObject resonse, String deviceId, String channelId, String uuid);
|
void onPublishHandlerForPlayBack(JSONObject resonse, String deviceId, String channelId, String uuid);
|
||||||
void onPublishHandlerForPlay(JSONObject resonse, String deviceId, String channelId, String uuid);
|
void onPublishHandlerForPlay(JSONObject resonse, String deviceId, String channelId, String uuid);
|
||||||
|
|
||||||
|
PlayResult play(String deviceId, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,19 +4,29 @@ import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||||
import com.genersoft.iot.vmp.conf.MediaServerConfig;
|
import com.genersoft.iot.vmp.conf.MediaServerConfig;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
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.ZLMHttpHookSubscribe;
|
||||||
|
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
import com.genersoft.iot.vmp.vmanager.play.PlayController;
|
import com.genersoft.iot.vmp.vmanager.play.PlayController;
|
||||||
|
import com.genersoft.iot.vmp.vmanager.play.bean.PlayResult;
|
||||||
import com.genersoft.iot.vmp.vmanager.service.IPlayService;
|
import com.genersoft.iot.vmp.vmanager.service.IPlayService;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.context.request.async.DeferredResult;
|
||||||
|
|
||||||
|
import javax.sip.message.Response;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class PlayServiceImpl implements IPlayService {
|
public class PlayServiceImpl implements IPlayService {
|
||||||
|
@ -26,12 +36,77 @@ public class PlayServiceImpl implements IPlayService {
|
||||||
@Autowired
|
@Autowired
|
||||||
private IVideoManagerStorager storager;
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SIPCommander cmder;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IRedisCatchStorage redisCatchStorage;
|
private IRedisCatchStorage redisCatchStorage;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DeferredResultHolder resultHolder;
|
private DeferredResultHolder resultHolder;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ZLMRESTfulUtils zlmresTfulUtils;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PlayResult play(String deviceId, String channelId, ZLMHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent) {
|
||||||
|
PlayResult playResult = new PlayResult();
|
||||||
|
Device device = storager.queryVideoDevice(deviceId);
|
||||||
|
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
|
||||||
|
playResult.setDevice(device);
|
||||||
|
UUID uuid = UUID.randomUUID();
|
||||||
|
playResult.setUuid(uuid.toString());
|
||||||
|
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>();
|
||||||
|
playResult.setResult(result);
|
||||||
|
// 录像查询以channelId作为deviceId查询
|
||||||
|
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result);
|
||||||
|
|
||||||
|
if (streamInfo == null) {
|
||||||
|
// 发送点播消息
|
||||||
|
cmder.playStreamCmd(device, channelId, (JSONObject response) -> {
|
||||||
|
logger.info("收到订阅消息: " + response.toJSONString());
|
||||||
|
onPublishHandlerForPlay(response, deviceId, channelId, uuid.toString());
|
||||||
|
if (hookEvent != null) {
|
||||||
|
hookEvent.response(response);
|
||||||
|
}
|
||||||
|
}, event -> {
|
||||||
|
RequestMessage msg = new RequestMessage();
|
||||||
|
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
|
||||||
|
Response response = event.getResponse();
|
||||||
|
msg.setData(String.format("点播失败, 错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
|
||||||
|
resultHolder.invokeResult(msg);
|
||||||
|
if (errorEvent != null) {
|
||||||
|
errorEvent.response(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
String streamId = streamInfo.getStreamId();
|
||||||
|
JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId);
|
||||||
|
if (rtpInfo.getBoolean("exist")) {
|
||||||
|
RequestMessage msg = new RequestMessage();
|
||||||
|
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
|
||||||
|
msg.setData(JSON.toJSONString(streamInfo));
|
||||||
|
resultHolder.invokeResult(msg);
|
||||||
|
} else {
|
||||||
|
redisCatchStorage.stopPlay(streamInfo);
|
||||||
|
storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
|
||||||
|
cmder.playStreamCmd(device, channelId, (JSONObject response) -> {
|
||||||
|
logger.info("收到订阅消息: " + response.toJSONString());
|
||||||
|
onPublishHandlerForPlay(response, deviceId, channelId, uuid.toString());
|
||||||
|
}, event -> {
|
||||||
|
RequestMessage msg = new RequestMessage();
|
||||||
|
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
|
||||||
|
Response response = event.getResponse();
|
||||||
|
msg.setData(String.format("点播失败, 错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
|
||||||
|
resultHolder.invokeResult(msg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return playResult;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPublishHandlerForPlay(JSONObject resonse, String deviceId, String channelId, String uuid) {
|
public void onPublishHandlerForPlay(JSONObject resonse, String deviceId, String channelId, String uuid) {
|
||||||
RequestMessage msg = new RequestMessage();
|
RequestMessage msg = new RequestMessage();
|
||||||
|
|
Loading…
Reference in New Issue