PlayController.java 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. package com.genersoft.iot.vmp.vmanager.play;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.JSONArray;
  4. import com.genersoft.iot.vmp.common.StreamInfo;
  5. import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
  6. import org.slf4j.Logger;
  7. import org.slf4j.LoggerFactory;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.beans.factory.annotation.Value;
  10. import org.springframework.http.HttpStatus;
  11. import org.springframework.http.ResponseEntity;
  12. import org.springframework.web.bind.annotation.CrossOrigin;
  13. import org.springframework.web.bind.annotation.GetMapping;
  14. import org.springframework.web.bind.annotation.PathVariable;
  15. import org.springframework.web.bind.annotation.PostMapping;
  16. import org.springframework.web.bind.annotation.RequestMapping;
  17. import org.springframework.web.bind.annotation.RestController;
  18. import com.alibaba.fastjson.JSONObject;
  19. import com.genersoft.iot.vmp.gb28181.bean.Device;
  20. import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
  21. import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  22. @CrossOrigin
  23. @RestController
  24. @RequestMapping("/api")
  25. public class PlayController {
  26. private final static Logger logger = LoggerFactory.getLogger(PlayController.class);
  27. @Autowired
  28. private SIPCommander cmder;
  29. @Autowired
  30. private IVideoManagerStorager storager;
  31. @Autowired
  32. private ZLMRESTfulUtils zlmresTfulUtils;
  33. @GetMapping("/play/{deviceId}/{channelId}")
  34. public ResponseEntity<String> play(@PathVariable String deviceId, @PathVariable String channelId,
  35. Integer getEncoding) {
  36. Device device = storager.queryVideoDevice(deviceId);
  37. StreamInfo streamInfo = storager.queryPlayByDevice(deviceId, channelId);
  38. if (streamInfo == null) {
  39. streamInfo = cmder.playStreamCmd(device, channelId);
  40. } else {
  41. String streamId = String.format("%08x", Integer.parseInt(streamInfo.getSsrc())).toUpperCase();
  42. JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId);
  43. if (rtpInfo.getBoolean("exist")) {
  44. return new ResponseEntity<String>(JSON.toJSONString(streamInfo), HttpStatus.OK);
  45. } else {
  46. storager.stopPlay(streamInfo);
  47. streamInfo = cmder.playStreamCmd(device, channelId);
  48. }
  49. }
  50. String streamId = String.format("%08x", Integer.parseInt(streamInfo.getSsrc())).toUpperCase();
  51. // 等待推流, TODO 默认超时30s
  52. boolean lockFlag = true;
  53. boolean rtpPushed = false;
  54. long startTime = System.currentTimeMillis();
  55. JSONObject rtpInfo = null;
  56. if (getEncoding == 1) {
  57. while (lockFlag) {
  58. try {
  59. if (System.currentTimeMillis() - startTime > 60 * 1000) {
  60. storager.stopPlay(streamInfo);
  61. logger.info("播放等待超时");
  62. return new ResponseEntity<String>("timeout", HttpStatus.OK);
  63. } else {
  64. streamInfo = storager.queryPlayByDevice(deviceId, channelId);
  65. if (!rtpPushed) {
  66. logger.info("查询RTP推流信息...");
  67. rtpInfo = zlmresTfulUtils.getRtpInfo(streamId);
  68. }
  69. if (rtpInfo != null && rtpInfo.getBoolean("exist") && streamInfo != null
  70. && streamInfo.getFlv() != null) {
  71. logger.info("查询流编码信息:" + streamInfo.getFlv());
  72. rtpPushed = true;
  73. Thread.sleep(2000);
  74. JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo("rtp", "rtmp", streamId);
  75. if (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online")) {
  76. lockFlag = false;
  77. logger.info("流编码信息已获取");
  78. JSONArray tracks = mediaInfo.getJSONArray("tracks");
  79. streamInfo.setTracks(tracks);
  80. storager.startPlay(streamInfo);
  81. } else {
  82. logger.info("流编码信息未获取,2秒后重试...");
  83. }
  84. } else {
  85. Thread.sleep(2000);
  86. continue;
  87. }
  88. }
  89. } catch (InterruptedException e) {
  90. e.printStackTrace();
  91. }
  92. }
  93. } else {
  94. String flv = storager.getMediaInfo().getLocalIP() + ":" + storager.getMediaInfo().getHttpPort() + "/rtp/"
  95. + streamId + ".flv";
  96. streamInfo.setFlv("http://" + flv);
  97. streamInfo.setWs_flv("ws://" + flv);
  98. storager.startPlay(streamInfo);
  99. }
  100. if (logger.isDebugEnabled()) {
  101. logger.debug(String.format("设备预览 API调用,deviceId:%s ,channelId:%s", deviceId, channelId));
  102. logger.debug("设备预览 API调用,ssrc:" + streamInfo.getSsrc() + ",ZLMedia streamId:"
  103. + Integer.toHexString(Integer.parseInt(streamInfo.getSsrc())));
  104. }
  105. if (streamInfo != null) {
  106. return new ResponseEntity<String>(JSON.toJSONString(streamInfo), HttpStatus.OK);
  107. } else {
  108. logger.warn("设备预览API调用失败!");
  109. return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR);
  110. }
  111. }
  112. @PostMapping("/play/{ssrc}/stop")
  113. public ResponseEntity<String> playStop(@PathVariable String ssrc) {
  114. cmder.streamByeCmd(ssrc);
  115. StreamInfo streamInfo = storager.queryPlayBySSRC(ssrc);
  116. if (streamInfo == null)
  117. return new ResponseEntity<String>(HttpStatus.PAYMENT_REQUIRED);
  118. storager.stopPlay(streamInfo);
  119. if (logger.isDebugEnabled()) {
  120. logger.debug(String.format("设备预览停止API调用,ssrc:%s", ssrc));
  121. }
  122. if (ssrc != null) {
  123. JSONObject json = new JSONObject();
  124. json.put("ssrc", ssrc);
  125. return new ResponseEntity<String>(json.toString(), HttpStatus.OK);
  126. } else {
  127. logger.warn("设备预览停止API调用失败!");
  128. return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR);
  129. }
  130. }
  131. }