Commit 1b44ba33671e27c3d206d875306b226c770b7980

Authored by panlinlin
1 parent e09e541c

完成向上级联->点播--002

src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java
@@ -15,6 +15,7 @@ import com.alibaba.fastjson.JSON; @@ -15,6 +15,7 @@ import com.alibaba.fastjson.JSON;
15 import com.genersoft.iot.vmp.gb28181.transmit.response.impl.*; 15 import com.genersoft.iot.vmp.gb28181.transmit.response.impl.*;
16 import com.genersoft.iot.vmp.gb28181.transmit.response.impl.*; 16 import com.genersoft.iot.vmp.gb28181.transmit.response.impl.*;
17 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; 17 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
  18 +import com.genersoft.iot.vmp.vmanager.service.IPlayService;
18 import org.slf4j.Logger; 19 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory; 20 import org.slf4j.LoggerFactory;
20 import org.springframework.beans.factory.annotation.Autowired; 21 import org.springframework.beans.factory.annotation.Autowired;
@@ -103,6 +104,9 @@ public class SIPProcessorFactory { @@ -103,6 +104,9 @@ public class SIPProcessorFactory {
103 @Autowired 104 @Autowired
104 private OtherResponseProcessor otherResponseProcessor; 105 private OtherResponseProcessor otherResponseProcessor;
105 106
  107 + @Autowired
  108 + private IPlayService playService;
  109 +
106 110
107 // 注:这里使用注解会导致循环依赖注入,暂用springBean 111 // 注:这里使用注解会导致循环依赖注入,暂用springBean
108 private SipProvider tcpSipProvider; 112 private SipProvider tcpSipProvider;
@@ -120,7 +124,9 @@ public class SIPProcessorFactory { @@ -120,7 +124,9 @@ public class SIPProcessorFactory {
120 processor.setTcpSipProvider(getTcpSipProvider()); 124 processor.setTcpSipProvider(getTcpSipProvider());
121 processor.setUdpSipProvider(getUdpSipProvider()); 125 processor.setUdpSipProvider(getUdpSipProvider());
122 126
  127 + processor.setCmder(cmder);
123 processor.setCmderFroPlatform(cmderFroPlatform); 128 processor.setCmderFroPlatform(cmderFroPlatform);
  129 + processor.setPlayService(playService);
124 processor.setStorager(storager); 130 processor.setStorager(storager);
125 return processor; 131 return processor;
126 } else if (Request.REGISTER.equals(method)) { 132 } else if (Request.REGISTER.equals(method)) {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java
@@ -10,19 +10,26 @@ import javax.sip.header.SubjectHeader; @@ -10,19 +10,26 @@ import javax.sip.header.SubjectHeader;
10 import javax.sip.message.Request; 10 import javax.sip.message.Request;
11 import javax.sip.message.Response; 11 import javax.sip.message.Response;
12 12
  13 +import com.alibaba.fastjson.JSONObject;
  14 +import com.genersoft.iot.vmp.gb28181.bean.Device;
13 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; 15 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
14 import com.genersoft.iot.vmp.gb28181.sdp.Codec; 16 import com.genersoft.iot.vmp.gb28181.sdp.Codec;
15 import com.genersoft.iot.vmp.gb28181.sdp.MediaDescription; 17 import com.genersoft.iot.vmp.gb28181.sdp.MediaDescription;
16 import com.genersoft.iot.vmp.gb28181.sdp.SdpParser; 18 import com.genersoft.iot.vmp.gb28181.sdp.SdpParser;
17 import com.genersoft.iot.vmp.gb28181.sdp.SessionDescription; 19 import com.genersoft.iot.vmp.gb28181.sdp.SessionDescription;
  20 +import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
  21 +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
18 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; 22 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
19 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; 23 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
20 import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor; 24 import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor;
21 import com.genersoft.iot.vmp.storager.IVideoManagerStorager; 25 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  26 +import com.genersoft.iot.vmp.vmanager.play.bean.PlayResult;
  27 +import com.genersoft.iot.vmp.vmanager.service.IPlayService;
22 import gov.nist.javax.sip.address.AddressImpl; 28 import gov.nist.javax.sip.address.AddressImpl;
23 import gov.nist.javax.sip.address.SipUri; 29 import gov.nist.javax.sip.address.SipUri;
24 import org.slf4j.Logger; 30 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory; 31 import org.slf4j.LoggerFactory;
  32 +import org.springframework.beans.factory.annotation.Autowired;
26 33
27 import java.io.IOException; 34 import java.io.IOException;
28 import java.text.ParseException; 35 import java.text.ParseException;
@@ -41,6 +48,10 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor { @@ -41,6 +48,10 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
41 48
42 private IVideoManagerStorager storager; 49 private IVideoManagerStorager storager;
43 50
  51 + private SIPCommander cmder;
  52 +
  53 + private IPlayService playService;
  54 +
44 /** 55 /**
45 * 处理invite请求 56 * 处理invite请求
46 * 57 *
@@ -119,7 +130,30 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor { @@ -119,7 +130,30 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
119 130
120 131
121 String ssrc = sdp.getSsrc(); 132 String ssrc = sdp.getSsrc();
  133 +
  134 + Device device = storager.queryVideoDeviceByPlatformIdAndChannelId(platformId, channelId);
  135 + if (device == null) {
  136 + logger.warn("点播平台{}的通道{}时未找到设备信息", platformId, channel);
  137 + response500Ack(evt);
  138 + return;
  139 + }
  140 +
122 // 通知下级推流, 141 // 通知下级推流,
  142 + PlayResult playResult = playService.play(device.getDeviceId(), channelId, (response)->{
  143 + // 收到推流, 回复200OK
  144 +
  145 + },(event -> {
  146 + // 未知错误。直接转发设备点播的错误
  147 + Response response = null;
  148 + try {
  149 + response = getMessageFactory().createResponse(event.getResponse().getStatusCode(), evt.getRequest());
  150 + getServerTransaction(evt).sendResponse(response);
  151 +
  152 + } catch (ParseException | SipException | InvalidArgumentException e) {
  153 + e.printStackTrace();
  154 + }
  155 + }));
  156 + playResult.getResult();
123 // 查找合适的端口推流, 157 // 查找合适的端口推流,
124 // 发送 200ok 158 // 发送 200ok
125 // 收到ack后调用推流接口 159 // 收到ack后调用推流接口
@@ -149,14 +183,16 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor { @@ -149,14 +183,16 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
149 } 183 }
150 184
151 /*** 185 /***
152 - * 回复404 186 + * 回复200 OK
153 * @param evt 187 * @param evt
154 * @throws SipException 188 * @throws SipException
155 * @throws InvalidArgumentException 189 * @throws InvalidArgumentException
156 * @throws ParseException 190 * @throws ParseException
157 */ 191 */
158 - private void response404Ack(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException {  
159 - Response response = getMessageFactory().createResponse(Response.NOT_FOUND, evt.getRequest()); 192 + private void responseAck(RequestEvent evt, String sdp) throws SipException, InvalidArgumentException, ParseException {
  193 + Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
  194 + ContentTypeHeader contentTypeHeader = getHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
  195 + response.setContent(sdp, contentTypeHeader);
160 getServerTransaction(evt).sendResponse(response); 196 getServerTransaction(evt).sendResponse(response);
161 } 197 }
162 198
@@ -173,6 +209,18 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor { @@ -173,6 +209,18 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
173 } 209 }
174 210
175 /*** 211 /***
  212 + * 回复404
  213 + * @param evt
  214 + * @throws SipException
  215 + * @throws InvalidArgumentException
  216 + * @throws ParseException
  217 + */
  218 + private void response404Ack(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException {
  219 + Response response = getMessageFactory().createResponse(Response.NOT_FOUND, evt.getRequest());
  220 + getServerTransaction(evt).sendResponse(response);
  221 + }
  222 +
  223 + /***
176 * 回复488 224 * 回复488
177 * @param evt 225 * @param evt
178 * @throws SipException 226 * @throws SipException
@@ -185,16 +233,14 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor { @@ -185,16 +233,14 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
185 } 233 }
186 234
187 /*** 235 /***
188 - * 回复200 OK 236 + * 回复500
189 * @param evt 237 * @param evt
190 * @throws SipException 238 * @throws SipException
191 * @throws InvalidArgumentException 239 * @throws InvalidArgumentException
192 * @throws ParseException 240 * @throws ParseException
193 */ 241 */
194 - private void responseAck(RequestEvent evt, String sdp) throws SipException, InvalidArgumentException, ParseException {  
195 - Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());  
196 - ContentTypeHeader contentTypeHeader = getHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");  
197 - response.setContent(sdp, contentTypeHeader); 242 + private void response500Ack(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException {
  243 + Response response = getMessageFactory().createResponse(Response.SERVER_INTERNAL_ERROR, evt.getRequest());
198 getServerTransaction(evt).sendResponse(response); 244 getServerTransaction(evt).sendResponse(response);
199 } 245 }
200 246
@@ -207,6 +253,8 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor { @@ -207,6 +253,8 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
207 253
208 254
209 255
  256 +
  257 +
210 public SIPCommanderFroPlatform getCmderFroPlatform() { 258 public SIPCommanderFroPlatform getCmderFroPlatform() {
211 return cmderFroPlatform; 259 return cmderFroPlatform;
212 } 260 }
@@ -222,4 +270,20 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor { @@ -222,4 +270,20 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor {
222 public void setStorager(IVideoManagerStorager storager) { 270 public void setStorager(IVideoManagerStorager storager) {
223 this.storager = storager; 271 this.storager = storager;
224 } 272 }
  273 +
  274 + public SIPCommander getCmder() {
  275 + return cmder;
  276 + }
  277 +
  278 + public void setCmder(SIPCommander cmder) {
  279 + this.cmder = cmder;
  280 + }
  281 +
  282 + public IPlayService getPlayService() {
  283 + return playService;
  284 + }
  285 +
  286 + public void setPlayService(IPlayService playService) {
  287 + this.playService = playService;
  288 + }
225 } 289 }
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java
@@ -234,4 +234,6 @@ public interface IVideoManagerStorager { @@ -234,4 +234,6 @@ public interface IVideoManagerStorager {
234 234
235 235
236 DeviceChannel queryChannelInParentPlatform(String platformId, String channelId); 236 DeviceChannel queryChannelInParentPlatform(String platformId, String channelId);
  237 +
  238 + Device queryVideoDeviceByPlatformIdAndChannelId(String platformId, String channelId);
237 } 239 }
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java
@@ -335,4 +335,9 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { @@ -335,4 +335,9 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
335 DeviceChannel channel = patformChannelMapper.queryChannelInParentPlatform(platformId, channelId); 335 DeviceChannel channel = patformChannelMapper.queryChannelInParentPlatform(platformId, channelId);
336 return channel; 336 return channel;
337 } 337 }
  338 +
  339 + @Override
  340 + public Device queryVideoDeviceByPlatformIdAndChannelId(String platformId, String channelId) {
  341 + return null;
  342 + }
338 } 343 }
src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java
@@ -10,6 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; @@ -10,6 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
10 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; 10 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
11 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; 11 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
12 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 12 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  13 +import com.genersoft.iot.vmp.vmanager.play.bean.PlayResult;
13 import com.genersoft.iot.vmp.vmanager.service.IPlayService; 14 import com.genersoft.iot.vmp.vmanager.service.IPlayService;
14 import org.slf4j.Logger; 15 import org.slf4j.Logger;
15 import org.slf4j.LoggerFactory; 16 import org.slf4j.LoggerFactory;
@@ -64,62 +65,19 @@ public class PlayController { @@ -64,62 +65,19 @@ public class PlayController {
64 @PathVariable String channelId) { 65 @PathVariable String channelId) {
65 66
66 67
67 - Device device = storager.queryVideoDevice(deviceId);  
68 - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);  
69 -  
70 - UUID uuid = UUID.randomUUID();  
71 - DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>();  
72 -  
73 - // 录像查询以channelId作为deviceId查询  
74 - resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result);  
75 -  
76 - if (streamInfo == null) {  
77 - // 发送点播消息  
78 - cmder.playStreamCmd(device, channelId, (JSONObject response) -> {  
79 - logger.info("收到订阅消息: " + response.toJSONString());  
80 - playService.onPublishHandlerForPlay(response, deviceId, channelId, uuid.toString());  
81 - }, event -> {  
82 - RequestMessage msg = new RequestMessage();  
83 - msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);  
84 - Response response = event.getResponse();  
85 - msg.setData(String.format("点播失败, 错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));  
86 - resultHolder.invokeResult(msg);  
87 - });  
88 - } else {  
89 - String streamId = streamInfo.getStreamId();  
90 - JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId);  
91 - if (rtpInfo.getBoolean("exist")) {  
92 - RequestMessage msg = new RequestMessage();  
93 - msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);  
94 - msg.setData(JSON.toJSONString(streamInfo));  
95 - resultHolder.invokeResult(msg);  
96 - } else {  
97 - redisCatchStorage.stopPlay(streamInfo);  
98 - storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());  
99 - cmder.playStreamCmd(device, channelId, (JSONObject response) -> {  
100 - logger.info("收到订阅消息: " + response.toJSONString());  
101 - playService.onPublishHandlerForPlay(response, deviceId, channelId, uuid.toString());  
102 - }, event -> {  
103 - RequestMessage msg = new RequestMessage();  
104 - msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);  
105 - Response response = event.getResponse();  
106 - msg.setData(String.format("点播失败, 错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));  
107 - resultHolder.invokeResult(msg);  
108 - });  
109 - }  
110 - } 68 + PlayResult playResult = playService.play(deviceId, channelId, null, null);
111 69
112 // 超时处理 70 // 超时处理
113 - result.onTimeout(()->{ 71 + playResult.getResult().onTimeout(()->{
114 logger.warn(String.format("设备点播超时,deviceId:%s ,channelId:%s", deviceId, channelId)); 72 logger.warn(String.format("设备点播超时,deviceId:%s ,channelId:%s", deviceId, channelId));
115 // 释放rtpserver 73 // 释放rtpserver
116 - cmder.closeRTPServer(device, channelId); 74 + cmder.closeRTPServer(playResult.getDevice(), channelId);
117 RequestMessage msg = new RequestMessage(); 75 RequestMessage msg = new RequestMessage();
118 - msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid); 76 + msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + playResult.getUuid());
119 msg.setData("Timeout"); 77 msg.setData("Timeout");
120 resultHolder.invokeResult(msg); 78 resultHolder.invokeResult(msg);
121 }); 79 });
122 - return result; 80 + return playResult.getResult();
123 } 81 }
124 82
125 @PostMapping("/play/{streamId}/stop") 83 @PostMapping("/play/{streamId}/stop")
src/main/java/com/genersoft/iot/vmp/vmanager/play/bean/PlayResult.java 0 → 100644
  1 +package com.genersoft.iot.vmp.vmanager.play.bean;
  2 +
  3 +import com.genersoft.iot.vmp.gb28181.bean.Device;
  4 +import org.springframework.http.ResponseEntity;
  5 +import org.springframework.web.context.request.async.DeferredResult;
  6 +
  7 +public class PlayResult {
  8 +
  9 + private DeferredResult<ResponseEntity<String>> result;
  10 + private String uuid;
  11 +
  12 + private Device device;
  13 +
  14 + public DeferredResult<ResponseEntity<String>> getResult() {
  15 + return result;
  16 + }
  17 +
  18 + public void setResult(DeferredResult<ResponseEntity<String>> result) {
  19 + this.result = result;
  20 + }
  21 +
  22 + public String getUuid() {
  23 + return uuid;
  24 + }
  25 +
  26 + public void setUuid(String uuid) {
  27 + this.uuid = uuid;
  28 + }
  29 +
  30 + public Device getDevice() {
  31 + return device;
  32 + }
  33 +
  34 + public void setDevice(Device device) {
  35 + this.device = device;
  36 + }
  37 +}
src/main/java/com/genersoft/iot/vmp/vmanager/service/IPlayService.java
@@ -2,6 +2,11 @@ package com.genersoft.iot.vmp.vmanager.service; @@ -2,6 +2,11 @@ package com.genersoft.iot.vmp.vmanager.service;
2 2
3 import com.alibaba.fastjson.JSONObject; 3 import com.alibaba.fastjson.JSONObject;
4 import com.genersoft.iot.vmp.common.StreamInfo; 4 import com.genersoft.iot.vmp.common.StreamInfo;
  5 +import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
  6 +import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
  7 +import com.genersoft.iot.vmp.vmanager.play.bean.PlayResult;
  8 +import org.springframework.http.ResponseEntity;
  9 +import org.springframework.web.context.request.async.DeferredResult;
5 10
6 /** 11 /**
7 * 点播处理 12 * 点播处理
@@ -10,4 +15,6 @@ public interface IPlayService { @@ -10,4 +15,6 @@ public interface IPlayService {
10 15
11 void onPublishHandlerForPlayBack(JSONObject resonse, String deviceId, String channelId, String uuid); 16 void onPublishHandlerForPlayBack(JSONObject resonse, String deviceId, String channelId, String uuid);
12 void onPublishHandlerForPlay(JSONObject resonse, String deviceId, String channelId, String uuid); 17 void onPublishHandlerForPlay(JSONObject resonse, String deviceId, String channelId, String uuid);
  18 +
  19 + PlayResult play(String deviceId, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
13 } 20 }
src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java
@@ -4,19 +4,29 @@ import com.alibaba.fastjson.JSON; @@ -4,19 +4,29 @@ import com.alibaba.fastjson.JSON;
4 import com.alibaba.fastjson.JSONObject; 4 import com.alibaba.fastjson.JSONObject;
5 import com.genersoft.iot.vmp.common.StreamInfo; 5 import com.genersoft.iot.vmp.common.StreamInfo;
6 import com.genersoft.iot.vmp.conf.MediaServerConfig; 6 import com.genersoft.iot.vmp.conf.MediaServerConfig;
  7 +import com.genersoft.iot.vmp.gb28181.bean.Device;
7 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; 8 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
  9 +import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
8 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 10 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
9 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; 11 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
  12 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
  13 +import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
  14 +import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
10 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 15 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
11 import com.genersoft.iot.vmp.storager.IVideoManagerStorager; 16 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
12 import com.genersoft.iot.vmp.vmanager.play.PlayController; 17 import com.genersoft.iot.vmp.vmanager.play.PlayController;
  18 +import com.genersoft.iot.vmp.vmanager.play.bean.PlayResult;
13 import com.genersoft.iot.vmp.vmanager.service.IPlayService; 19 import com.genersoft.iot.vmp.vmanager.service.IPlayService;
14 import org.slf4j.Logger; 20 import org.slf4j.Logger;
15 import org.slf4j.LoggerFactory; 21 import org.slf4j.LoggerFactory;
16 import org.springframework.beans.factory.annotation.Autowired; 22 import org.springframework.beans.factory.annotation.Autowired;
  23 +import org.springframework.http.ResponseEntity;
17 import org.springframework.stereotype.Service; 24 import org.springframework.stereotype.Service;
  25 +import org.springframework.web.context.request.async.DeferredResult;
18 26
  27 +import javax.sip.message.Response;
19 import java.text.DecimalFormat; 28 import java.text.DecimalFormat;
  29 +import java.util.UUID;
20 30
21 @Service 31 @Service
22 public class PlayServiceImpl implements IPlayService { 32 public class PlayServiceImpl implements IPlayService {
@@ -27,11 +37,76 @@ public class PlayServiceImpl implements IPlayService { @@ -27,11 +37,76 @@ public class PlayServiceImpl implements IPlayService {
27 private IVideoManagerStorager storager; 37 private IVideoManagerStorager storager;
28 38
29 @Autowired 39 @Autowired
  40 + private SIPCommander cmder;
  41 +
  42 + @Autowired
30 private IRedisCatchStorage redisCatchStorage; 43 private IRedisCatchStorage redisCatchStorage;
31 44
32 @Autowired 45 @Autowired
33 private DeferredResultHolder resultHolder; 46 private DeferredResultHolder resultHolder;
34 47
  48 + @Autowired
  49 + private ZLMRESTfulUtils zlmresTfulUtils;
  50 +
  51 +
  52 + @Override
  53 + public PlayResult play(String deviceId, String channelId, ZLMHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent) {
  54 + PlayResult playResult = new PlayResult();
  55 + Device device = storager.queryVideoDevice(deviceId);
  56 + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
  57 + playResult.setDevice(device);
  58 + UUID uuid = UUID.randomUUID();
  59 + playResult.setUuid(uuid.toString());
  60 + DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>();
  61 + playResult.setResult(result);
  62 + // 录像查询以channelId作为deviceId查询
  63 + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result);
  64 +
  65 + if (streamInfo == null) {
  66 + // 发送点播消息
  67 + cmder.playStreamCmd(device, channelId, (JSONObject response) -> {
  68 + logger.info("收到订阅消息: " + response.toJSONString());
  69 + onPublishHandlerForPlay(response, deviceId, channelId, uuid.toString());
  70 + if (hookEvent != null) {
  71 + hookEvent.response(response);
  72 + }
  73 + }, event -> {
  74 + RequestMessage msg = new RequestMessage();
  75 + msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
  76 + Response response = event.getResponse();
  77 + msg.setData(String.format("点播失败, 错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
  78 + resultHolder.invokeResult(msg);
  79 + if (errorEvent != null) {
  80 + errorEvent.response(event);
  81 + }
  82 + });
  83 + } else {
  84 + String streamId = streamInfo.getStreamId();
  85 + JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId);
  86 + if (rtpInfo.getBoolean("exist")) {
  87 + RequestMessage msg = new RequestMessage();
  88 + msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
  89 + msg.setData(JSON.toJSONString(streamInfo));
  90 + resultHolder.invokeResult(msg);
  91 + } else {
  92 + redisCatchStorage.stopPlay(streamInfo);
  93 + storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
  94 + cmder.playStreamCmd(device, channelId, (JSONObject response) -> {
  95 + logger.info("收到订阅消息: " + response.toJSONString());
  96 + onPublishHandlerForPlay(response, deviceId, channelId, uuid.toString());
  97 + }, event -> {
  98 + RequestMessage msg = new RequestMessage();
  99 + msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
  100 + Response response = event.getResponse();
  101 + msg.setData(String.format("点播失败, 错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
  102 + resultHolder.invokeResult(msg);
  103 + });
  104 + }
  105 + }
  106 +
  107 + return playResult;
  108 + }
  109 +
35 @Override 110 @Override
36 public void onPublishHandlerForPlay(JSONObject resonse, String deviceId, String channelId, String uuid) { 111 public void onPublishHandlerForPlay(JSONObject resonse, String deviceId, String channelId, String uuid) {
37 RequestMessage msg = new RequestMessage(); 112 RequestMessage msg = new RequestMessage();