PlayServiceImpl.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. package com.genersoft.iot.vmp.service.impl;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.JSONArray;
  4. import com.alibaba.fastjson.JSONObject;
  5. import com.genersoft.iot.vmp.common.StreamInfo;
  6. import com.genersoft.iot.vmp.conf.UserSetup;
  7. import com.genersoft.iot.vmp.gb28181.bean.Device;
  8. import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
  9. import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
  10. import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
  11. import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
  12. import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
  13. import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
  14. import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
  15. import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
  16. import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  17. import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  18. import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
  19. import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
  20. import com.genersoft.iot.vmp.service.IMediaService;
  21. import com.genersoft.iot.vmp.service.IPlayService;
  22. import gov.nist.javax.sip.stack.SIPDialog;
  23. import org.slf4j.Logger;
  24. import org.slf4j.LoggerFactory;
  25. import org.springframework.beans.factory.annotation.Autowired;
  26. import org.springframework.beans.factory.annotation.Value;
  27. import org.springframework.http.HttpStatus;
  28. import org.springframework.http.ResponseEntity;
  29. import org.springframework.stereotype.Service;
  30. import org.springframework.util.ResourceUtils;
  31. import org.springframework.web.context.request.async.DeferredResult;
  32. import javax.sip.ClientTransaction;
  33. import javax.sip.Dialog;
  34. import javax.sip.header.CallIdHeader;
  35. import javax.sip.message.Response;
  36. import java.io.File;
  37. import java.io.FileNotFoundException;
  38. import java.util.UUID;
  39. @Service
  40. public class PlayServiceImpl implements IPlayService {
  41. private final static Logger logger = LoggerFactory.getLogger(PlayServiceImpl.class);
  42. @Autowired
  43. private IVideoManagerStorager storager;
  44. @Autowired
  45. private SIPCommander cmder;
  46. @Autowired
  47. private IRedisCatchStorage redisCatchStorage;
  48. @Autowired
  49. private DeferredResultHolder resultHolder;
  50. @Autowired
  51. private ZLMRESTfulUtils zlmresTfulUtils;
  52. @Autowired
  53. private IMediaService mediaService;
  54. @Autowired
  55. private VideoStreamSessionManager streamSession;
  56. @Autowired
  57. private UserSetup userSetup;
  58. @Override
  59. public PlayResult play(String deviceId, String channelId, ZLMHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent) {
  60. PlayResult playResult = new PlayResult();
  61. Device device = storager.queryVideoDevice(deviceId);
  62. StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
  63. playResult.setDevice(device);
  64. UUID uuid = UUID.randomUUID();
  65. playResult.setUuid(uuid.toString());
  66. DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(userSetup.getPlayTimeout());
  67. playResult.setResult(result);
  68. // 录像查询以channelId作为deviceId查询
  69. resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result);
  70. // 超时处理
  71. result.onTimeout(()->{
  72. logger.warn(String.format("设备点播超时,deviceId:%s ,channelId:%s", deviceId, channelId));
  73. // 释放rtpserver
  74. cmder.closeRTPServer(playResult.getDevice(), channelId);
  75. RequestMessage msg = new RequestMessage();
  76. msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + playResult.getUuid());
  77. WVPResult wvpResult = new WVPResult();
  78. wvpResult.setCode(-1);
  79. wvpResult.setMsg("Timeout");
  80. msg.setData(wvpResult);
  81. resultHolder.invokeResult(msg);
  82. });
  83. result.onCompletion(()->{
  84. // 点播结束时调用截图接口
  85. try {
  86. String path = ResourceUtils.getURL("classpath:").getPath()+"static/static/snap/";
  87. String fileName = deviceId + "_" + channelId + ".jpg";
  88. ResponseEntity responseEntity = (ResponseEntity)result.getResult();
  89. if (responseEntity != null && responseEntity.getStatusCode() == HttpStatus.OK) {
  90. WVPResult wvpResult = (WVPResult)responseEntity.getBody();
  91. if (wvpResult.getCode() == 0) {
  92. StreamInfo streamInfoForSuccess = (StreamInfo)wvpResult.getData();
  93. String flvUrl = streamInfoForSuccess.getFlv();
  94. // 请求截图
  95. zlmresTfulUtils.getSnap(flvUrl, 5, 1, path, fileName);
  96. }
  97. }
  98. System.out.println(path);
  99. } catch (FileNotFoundException e) {
  100. e.printStackTrace();
  101. }
  102. });
  103. if (streamInfo == null) {
  104. // 发送点播消息
  105. cmder.playStreamCmd(device, channelId, (JSONObject response) -> {
  106. logger.info("收到订阅消息: " + response.toJSONString());
  107. onPublishHandlerForPlay(response, deviceId, channelId, uuid.toString());
  108. if (hookEvent != null) {
  109. hookEvent.response(response);
  110. }
  111. }, event -> {
  112. RequestMessage msg = new RequestMessage();
  113. msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
  114. Response response = event.getResponse();
  115. cmder.closeRTPServer(playResult.getDevice(), channelId);
  116. WVPResult wvpResult = new WVPResult();
  117. wvpResult.setCode(-1);
  118. wvpResult.setMsg(String.format("点播失败, 错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
  119. msg.setData(wvpResult);
  120. resultHolder.invokeResult(msg);
  121. if (errorEvent != null) {
  122. errorEvent.response(event);
  123. }
  124. });
  125. } else {
  126. String streamId = streamInfo.getStreamId();
  127. if (streamId == null) {
  128. RequestMessage msg = new RequestMessage();
  129. msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
  130. WVPResult wvpResult = new WVPResult();
  131. wvpResult.setCode(-1);
  132. wvpResult.setMsg(String.format("点播失败, redis缓存streamId等于null"));
  133. msg.setData(wvpResult);
  134. resultHolder.invokeResult(msg);
  135. return playResult;
  136. }
  137. JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId);
  138. if (rtpInfo != null && rtpInfo.getBoolean("exist")) {
  139. RequestMessage msg = new RequestMessage();
  140. msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
  141. WVPResult wvpResult = new WVPResult();
  142. wvpResult.setCode(0);
  143. wvpResult.setMsg("success");
  144. wvpResult.setData(streamInfo);
  145. msg.setData(wvpResult);
  146. resultHolder.invokeResult(msg);
  147. if (hookEvent != null) {
  148. hookEvent.response(JSONObject.parseObject(JSON.toJSONString(streamInfo)));
  149. }
  150. } else {
  151. redisCatchStorage.stopPlay(streamInfo);
  152. storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
  153. cmder.playStreamCmd(device, channelId, (JSONObject response) -> {
  154. logger.info("收到订阅消息: " + response.toJSONString());
  155. onPublishHandlerForPlay(response, deviceId, channelId, uuid.toString());
  156. }, event -> {
  157. cmder.closeRTPServer(playResult.getDevice(), channelId);
  158. RequestMessage msg = new RequestMessage();
  159. msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
  160. Response response = event.getResponse();
  161. WVPResult wvpResult = new WVPResult();
  162. wvpResult.setCode(-1);
  163. wvpResult.setMsg(String.format("点播失败, 错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
  164. msg.setData(wvpResult);
  165. resultHolder.invokeResult(msg);
  166. });
  167. }
  168. }
  169. return playResult;
  170. }
  171. @Override
  172. public void onPublishHandlerForPlay(JSONObject resonse, String deviceId, String channelId, String uuid) {
  173. RequestMessage msg = new RequestMessage();
  174. msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
  175. StreamInfo streamInfo = onPublishHandler(resonse, deviceId, channelId, uuid);
  176. if (streamInfo != null) {
  177. DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId);
  178. if (deviceChannel != null) {
  179. deviceChannel.setStreamId(streamInfo.getStreamId());
  180. storager.startPlay(deviceId, channelId, streamInfo.getStreamId());
  181. }
  182. ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId);
  183. SIPDialog dialog = (SIPDialog)transaction.getDialog();
  184. StreamInfo.TransactionInfo transactionInfo = new StreamInfo.TransactionInfo();
  185. transactionInfo.callId = dialog.getCallId().getCallId();
  186. transactionInfo.localTag = dialog.getLocalTag();
  187. transactionInfo.remoteTag = dialog.getRemoteTag();
  188. transactionInfo.branch = dialog.getFirstTransactionInt().getBranchId();
  189. streamInfo.setTransactionInfo(transactionInfo);
  190. redisCatchStorage.startPlay(streamInfo);
  191. msg.setData(JSON.toJSONString(streamInfo));
  192. WVPResult wvpResult = new WVPResult();
  193. wvpResult.setCode(0);
  194. wvpResult.setMsg("sucess");
  195. wvpResult.setData(streamInfo);
  196. msg.setData(wvpResult);
  197. resultHolder.invokeResult(msg);
  198. } else {
  199. logger.warn("设备预览API调用失败!");
  200. msg.setData("设备预览API调用失败!");
  201. resultHolder.invokeResult(msg);
  202. }
  203. }
  204. @Override
  205. public void onPublishHandlerForPlayBack(JSONObject resonse, String deviceId, String channelId, String uuid) {
  206. RequestMessage msg = new RequestMessage();
  207. msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
  208. StreamInfo streamInfo = onPublishHandler(resonse, deviceId, channelId, uuid);
  209. if (streamInfo != null) {
  210. redisCatchStorage.startPlayback(streamInfo);
  211. msg.setData(JSON.toJSONString(streamInfo));
  212. resultHolder.invokeResult(msg);
  213. } else {
  214. logger.warn("设备预览API调用失败!");
  215. msg.setData("设备预览API调用失败!");
  216. resultHolder.invokeResult(msg);
  217. }
  218. }
  219. public StreamInfo onPublishHandler(JSONObject resonse, String deviceId, String channelId, String uuid) {
  220. String streamId = resonse.getString("stream");
  221. JSONArray tracks = resonse.getJSONArray("tracks");
  222. StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream("rtp", streamId, tracks);
  223. streamInfo.setDeviceID(deviceId);
  224. streamInfo.setChannelId(channelId);
  225. return streamInfo;
  226. }
  227. }