PlaybackController.java 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. package com.genersoft.iot.vmp.gb28181.controller;
  2. import com.genersoft.iot.vmp.common.InviteInfo;
  3. import com.genersoft.iot.vmp.common.InviteSessionType;
  4. import com.genersoft.iot.vmp.common.StreamInfo;
  5. import com.genersoft.iot.vmp.conf.UserSetting;
  6. import com.genersoft.iot.vmp.conf.exception.ControllerException;
  7. import com.genersoft.iot.vmp.conf.exception.ServiceException;
  8. import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
  9. import com.genersoft.iot.vmp.conf.security.JwtUtils;
  10. import com.genersoft.iot.vmp.gb28181.bean.Device;
  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.gb28181.service.IDeviceService;
  15. import com.genersoft.iot.vmp.gb28181.service.IInviteStreamService;
  16. import com.genersoft.iot.vmp.gb28181.service.IPlayService;
  17. import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
  18. import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
  19. import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
  20. import com.genersoft.iot.vmp.vmanager.bean.StreamContent;
  21. import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
  22. import io.swagger.v3.oas.annotations.Operation;
  23. import io.swagger.v3.oas.annotations.Parameter;
  24. import io.swagger.v3.oas.annotations.security.SecurityRequirement;
  25. import io.swagger.v3.oas.annotations.tags.Tag;
  26. import lombok.extern.slf4j.Slf4j;
  27. import org.springframework.beans.factory.annotation.Autowired;
  28. import org.springframework.util.ObjectUtils;
  29. import org.springframework.web.bind.annotation.GetMapping;
  30. import org.springframework.web.bind.annotation.PathVariable;
  31. import org.springframework.web.bind.annotation.RequestMapping;
  32. import org.springframework.web.bind.annotation.RestController;
  33. import org.springframework.web.context.request.async.DeferredResult;
  34. import javax.servlet.http.HttpServletRequest;
  35. import javax.sip.InvalidArgumentException;
  36. import javax.sip.SipException;
  37. import java.net.MalformedURLException;
  38. import java.net.URL;
  39. import java.text.ParseException;
  40. import java.util.UUID;
  41. /**
  42. * @author lin
  43. */
  44. @Tag(name = "视频回放")
  45. @Slf4j
  46. @RestController
  47. @RequestMapping("/api/playback")
  48. public class PlaybackController {
  49. @Autowired
  50. private SIPCommander cmder;
  51. @Autowired
  52. private IVideoManagerStorage storager;
  53. @Autowired
  54. private IInviteStreamService inviteStreamService;
  55. @Autowired
  56. private IPlayService playService;
  57. @Autowired
  58. private DeferredResultHolder resultHolder;
  59. @Autowired
  60. private UserSetting userSetting;
  61. @Autowired
  62. private IDeviceService deviceService;
  63. @Operation(summary = "开始视频回放", security = @SecurityRequirement(name = JwtUtils.HEADER))
  64. @Parameter(name = "deviceId", description = "设备国标编号", required = true)
  65. @Parameter(name = "channelId", description = "通道国标编号", required = true)
  66. @Parameter(name = "startTime", description = "开始时间", required = true)
  67. @Parameter(name = "endTime", description = "结束时间", required = true)
  68. @GetMapping("/start/{deviceId}/{channelId}")
  69. public DeferredResult<WVPResult<StreamContent>> start(HttpServletRequest request, @PathVariable String deviceId, @PathVariable String channelId,
  70. String startTime, String endTime) {
  71. if (log.isDebugEnabled()) {
  72. log.debug(String.format("设备回放 API调用,deviceId:%s ,channelId:%s", deviceId, channelId));
  73. }
  74. String uuid = UUID.randomUUID().toString();
  75. String key = DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId;
  76. DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue());
  77. resultHolder.put(key, uuid, result);
  78. RequestMessage requestMessage = new RequestMessage();
  79. requestMessage.setKey(key);
  80. requestMessage.setId(uuid);
  81. playService.playBack(deviceId, channelId, startTime, endTime,
  82. (code, msg, data)->{
  83. WVPResult<StreamContent> wvpResult = new WVPResult<>();
  84. if (code == InviteErrorCode.SUCCESS.getCode()) {
  85. wvpResult.setCode(ErrorCode.SUCCESS.getCode());
  86. wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());
  87. if (data != null) {
  88. StreamInfo streamInfo = (StreamInfo)data;
  89. if (userSetting.getUseSourceIpAsStreamIp()) {
  90. streamInfo=streamInfo.clone();//深拷贝
  91. String host;
  92. try {
  93. URL url=new URL(request.getRequestURL().toString());
  94. host=url.getHost();
  95. } catch (MalformedURLException e) {
  96. host=request.getLocalAddr();
  97. }
  98. streamInfo.channgeStreamIp(host);
  99. }
  100. wvpResult.setData(new StreamContent(streamInfo));
  101. }
  102. }else {
  103. wvpResult.setCode(code);
  104. wvpResult.setMsg(msg);
  105. }
  106. requestMessage.setData(wvpResult);
  107. resultHolder.invokeResult(requestMessage);
  108. });
  109. return result;
  110. }
  111. @Operation(summary = "停止视频回放", security = @SecurityRequirement(name = JwtUtils.HEADER))
  112. @Parameter(name = "deviceId", description = "设备国标编号", required = true)
  113. @Parameter(name = "channelId", description = "通道国标编号", required = true)
  114. @Parameter(name = "stream", description = "流ID", required = true)
  115. @GetMapping("/stop/{deviceId}/{channelId}/{stream}")
  116. public void playStop(
  117. @PathVariable String deviceId,
  118. @PathVariable String channelId,
  119. @PathVariable String stream) {
  120. if (ObjectUtils.isEmpty(deviceId) || ObjectUtils.isEmpty(channelId) || ObjectUtils.isEmpty(stream)) {
  121. throw new ControllerException(ErrorCode.ERROR400);
  122. }
  123. Device device = deviceService.getDeviceByDeviceId(deviceId);
  124. if (device == null) {
  125. throw new ControllerException(ErrorCode.ERROR400.getCode(), "设备:" + deviceId + " 未找到");
  126. }
  127. try {
  128. cmder.streamByeCmd(device, channelId, stream, null);
  129. } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) {
  130. throw new ControllerException(ErrorCode.ERROR100.getCode(), "发送bye失败: " + e.getMessage());
  131. }
  132. }
  133. @Operation(summary = "回放暂停", security = @SecurityRequirement(name = JwtUtils.HEADER))
  134. @Parameter(name = "streamId", description = "回放流ID", required = true)
  135. @GetMapping("/pause/{streamId}")
  136. public void playPause(@PathVariable String streamId) {
  137. log.info("playPause: "+streamId);
  138. try {
  139. playService.pauseRtp(streamId);
  140. } catch (ServiceException e) {
  141. throw new ControllerException(ErrorCode.ERROR400.getCode(), e.getMessage());
  142. } catch (InvalidArgumentException | ParseException | SipException e) {
  143. throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
  144. }
  145. }
  146. @Operation(summary = "回放恢复", security = @SecurityRequirement(name = JwtUtils.HEADER))
  147. @Parameter(name = "streamId", description = "回放流ID", required = true)
  148. @GetMapping("/resume/{streamId}")
  149. public void playResume(@PathVariable String streamId) {
  150. log.info("playResume: "+streamId);
  151. try {
  152. playService.resumeRtp(streamId);
  153. } catch (ServiceException e) {
  154. throw new ControllerException(ErrorCode.ERROR400.getCode(), e.getMessage());
  155. } catch (InvalidArgumentException | ParseException | SipException e) {
  156. throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
  157. }
  158. }
  159. @Operation(summary = "回放拖动播放", security = @SecurityRequirement(name = JwtUtils.HEADER))
  160. @Parameter(name = "streamId", description = "回放流ID", required = true)
  161. @Parameter(name = "seekTime", description = "拖动偏移量,单位s", required = true)
  162. @GetMapping("/seek/{streamId}/{seekTime}")
  163. public void playSeek(@PathVariable String streamId, @PathVariable long seekTime) {
  164. log.info("playSeek: "+streamId+", "+seekTime);
  165. InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId);
  166. if (null == inviteInfo || inviteInfo.getStreamInfo() == null) {
  167. log.warn("streamId不存在!");
  168. throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
  169. }
  170. Device device = deviceService.getDeviceByDeviceId(inviteInfo.getDeviceId());
  171. try {
  172. cmder.playSeekCmd(device, inviteInfo.getStreamInfo(), seekTime);
  173. } catch (InvalidArgumentException | ParseException | SipException e) {
  174. throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
  175. }
  176. }
  177. @Operation(summary = "回放倍速播放", security = @SecurityRequirement(name = JwtUtils.HEADER))
  178. @Parameter(name = "streamId", description = "回放流ID", required = true)
  179. @Parameter(name = "speed", description = "倍速0.25 0.5 1、2、4", required = true)
  180. @GetMapping("/speed/{streamId}/{speed}")
  181. public void playSpeed(@PathVariable String streamId, @PathVariable Double speed) {
  182. log.info("playSpeed: "+streamId+", "+speed);
  183. InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId);
  184. if (null == inviteInfo || inviteInfo.getStreamInfo() == null) {
  185. log.warn("streamId不存在!");
  186. throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
  187. }
  188. if(speed != 0.25 && speed != 0.5 && speed != 1 && speed != 2.0 && speed != 4.0) {
  189. log.warn("不支持的speed: " + speed);
  190. throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持的speed(0.25 0.5 1、2、4)");
  191. }
  192. Device device = deviceService.getDeviceByDeviceId(inviteInfo.getDeviceId());
  193. try {
  194. cmder.playSpeedCmd(device, inviteInfo.getStreamInfo(), speed);
  195. } catch (InvalidArgumentException | ParseException | SipException e) {
  196. throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
  197. }
  198. }
  199. }