From 1b200bcc904d088b31ceaf1e9261b5433d9322a6 Mon Sep 17 00:00:00 2001 From: Lawrence <1934378145@qq.com> Date: 星期五, 15 一月 2021 00:00:45 +0800 Subject: [PATCH] 将上级平台标识改为serverGBId --- src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java | 284 +++++++++++++++++++++++++++++++++++++++----------------- 1 files changed, 196 insertions(+), 88 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java index feb96df..3bd828a 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java @@ -3,7 +3,14 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.conf.MediaServerConfig; +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; +import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; +import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +import com.genersoft.iot.vmp.vmanager.service.IPlayService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -21,6 +28,11 @@ import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; +import org.springframework.web.context.request.async.DeferredResult; + +import javax.sip.message.Response; +import java.text.DecimalFormat; +import java.util.UUID; @CrossOrigin @RestController @@ -36,115 +48,211 @@ private IVideoManagerStorager storager; @Autowired + private IRedisCatchStorage redisCatchStorage; + + @Autowired private ZLMRESTfulUtils zlmresTfulUtils; - @GetMapping("/play/{deviceId}/{channelId}") - public ResponseEntity<String> play(@PathVariable String deviceId, @PathVariable String channelId, - Integer getEncoding) { + @Autowired + private DeferredResultHolder resultHolder; - if (getEncoding == null) getEncoding = 0; + @Autowired + private IPlayService playService; + + @GetMapping("/play/{deviceId}/{channelId}") + public DeferredResult<ResponseEntity<String>> play(@PathVariable String deviceId, + @PathVariable String channelId) { + + Device device = storager.queryVideoDevice(deviceId); - StreamInfo streamInfo = storager.queryPlayByDevice(deviceId, channelId); + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); + + UUID uuid = UUID.randomUUID(); + DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(); + + // 褰曞儚鏌ヨ浠hannelId浣滀负deviceId鏌ヨ + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result); if (streamInfo == null) { - streamInfo = cmder.playStreamCmd(device, channelId); + // 鍙戦�佺偣鎾秷鎭� + 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 = String.format("%08x", Integer.parseInt(streamInfo.getSsrc())).toUpperCase(); + String streamId = streamInfo.getStreamId(); JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId); if (rtpInfo.getBoolean("exist")) { - return new ResponseEntity<String>(JSON.toJSONString(streamInfo), HttpStatus.OK); + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid); + msg.setData(JSON.toJSONString(streamInfo)); + resultHolder.invokeResult(msg); } else { - storager.stopPlay(streamInfo); - streamInfo = cmder.playStreamCmd(device, channelId); + 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); + }); } - } - String streamId = String.format("%08x", Integer.parseInt(streamInfo.getSsrc())).toUpperCase(); - // 绛夊緟鎺ㄦ祦, TODO 榛樿瓒呮椂30s - boolean lockFlag = true; - boolean rtpPushed = false; - long startTime = System.currentTimeMillis(); - JSONObject rtpInfo = null; - if (getEncoding == 1) { - while (lockFlag) { - try { - if (System.currentTimeMillis() - startTime > 60 * 1000) { - storager.stopPlay(streamInfo); - logger.info("鎾斁绛夊緟瓒呮椂"); - return new ResponseEntity<String>("timeout", HttpStatus.OK); - } else { - streamInfo = storager.queryPlayByDevice(deviceId, channelId); - if (!rtpPushed) { - logger.info("鏌ヨRTP鎺ㄦ祦淇℃伅..."); - rtpInfo = zlmresTfulUtils.getRtpInfo(streamId); - } - if (rtpInfo != null && rtpInfo.getBoolean("exist") && streamInfo != null - && streamInfo.getFlv() != null) { - logger.info("鏌ヨ娴佺紪鐮佷俊鎭細" + streamInfo.getFlv()); - rtpPushed = true; - Thread.sleep(2000); - JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo("rtp", "rtmp", streamId); - if (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online")) { - lockFlag = false; - logger.info("娴佺紪鐮佷俊鎭凡鑾峰彇"); - JSONArray tracks = mediaInfo.getJSONArray("tracks"); - streamInfo.setTracks(tracks); - storager.startPlay(streamInfo); - } else { - logger.info("娴佺紪鐮佷俊鎭湭鑾峰彇锛�2绉掑悗閲嶈瘯..."); - } - } else { - Thread.sleep(2000); - continue; - } - } - } catch (InterruptedException e) { - e.printStackTrace(); + // 瓒呮椂澶勭悊 + result.onTimeout(()->{ + logger.warn(String.format("璁惧鐐规挱瓒呮椂锛宒eviceId锛�%s 锛宑hannelId锛�%s", deviceId, channelId)); + // 閲婃斁rtpserver + cmder.closeRTPServer(device, channelId); + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid); + msg.setData("Timeout"); + resultHolder.invokeResult(msg); + }); + return result; + } + + @PostMapping("/play/{streamId}/stop") + public DeferredResult<ResponseEntity<String>> playStop(@PathVariable String streamId) { + + logger.debug(String.format("璁惧棰勮/鍥炴斁鍋滄API璋冪敤锛宻treamId锛�%s", streamId)); + + UUID uuid = UUID.randomUUID(); + DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(); + + // 褰曞儚鏌ヨ浠hannelId浣滀负deviceId鏌ヨ + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_STOP + uuid, result); + + cmder.streamByeCmd(streamId, event -> { + StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId); + if (streamInfo == null) { + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid); + msg.setData("streamId not found"); + resultHolder.invokeResult(msg); + }else { + redisCatchStorage.stopPlay(streamInfo); + storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_STOP + uuid); + Response response = event.getResponse(); + msg.setData(String.format("success")); + resultHolder.invokeResult(msg); + } + }); + + if (streamId != null) { + JSONObject json = new JSONObject(); + json.put("streamId", streamId); + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid); + msg.setData(json.toString()); + resultHolder.invokeResult(msg); + } else { + logger.warn("璁惧棰勮/鍥炴斁鍋滄API璋冪敤澶辫触锛�"); + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid); + msg.setData("streamId null"); + resultHolder.invokeResult(msg); + } + + // 瓒呮椂澶勭悊 + result.onTimeout(()->{ + logger.warn(String.format("璁惧棰勮/鍥炴斁鍋滄瓒呮椂锛宻treamId锛�%s ", streamId)); + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_STOP + uuid); + msg.setData("Timeout"); + resultHolder.invokeResult(msg); + }); + return result; + } + + /** + * 灏嗕笉鏄痟264鐨勮棰戦�氳繃ffmpeg 杞爜涓篽264 + aac + * @param streamId 娴両D + * @return + */ + @PostMapping("/play/{streamId}/convert") + public ResponseEntity<String> playConvert(@PathVariable String streamId) { + StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId); + if (streamInfo == null) { + logger.warn("瑙嗛杞爜API璋冪敤澶辫触锛�, 瑙嗛娴佸凡缁忓仠姝�!"); + return new ResponseEntity<String>("鏈壘鍒拌棰戞祦淇℃伅, 瑙嗛娴佸彲鑳藉凡缁忓仠姝�", HttpStatus.OK); + } + JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId); + if (!rtpInfo.getBoolean("exist")) { + logger.warn("瑙嗛杞爜API璋冪敤澶辫触锛�, 瑙嗛娴佸凡鍋滄鎺ㄦ祦!"); + return new ResponseEntity<String>("鎺ㄦ祦淇℃伅鍦ㄦ祦濯掍綋涓笉瀛樺湪, 瑙嗛娴佸彲鑳藉凡鍋滄鎺ㄦ祦", HttpStatus.OK); + } else { + MediaServerConfig mediaInfo = redisCatchStorage.getMediaInfo(); + String dstUrl = String.format("rtmp://%s:%s/convert/%s", "127.0.0.1", mediaInfo.getRtmpPort(), + streamId ); + String srcUrl = String.format("rtsp://%s:%s/rtp/%s", "127.0.0.1", mediaInfo.getRtspPort(), streamId); + JSONObject jsonObject = zlmresTfulUtils.addFFmpegSource(srcUrl, dstUrl, "1000000"); + System.out.println(jsonObject); + JSONObject result = new JSONObject(); + if (jsonObject != null && jsonObject.getInteger("code") == 0) { + result.put("code", 0); + JSONObject data = jsonObject.getJSONObject("data"); + if (data != null) { + result.put("key", data.getString("key")); + StreamInfo streamInfoResult = new StreamInfo(); + streamInfoResult.setRtmp(dstUrl); + streamInfoResult.setRtsp(String.format("rtsp://%s:%s/convert/%s", mediaInfo.getWanIp(), mediaInfo.getRtspPort(), streamId)); + streamInfoResult.setStreamId(streamId); + streamInfoResult.setFlv(String.format("http://%s:%s/convert/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); + streamInfoResult.setWs_flv(String.format("ws://%s:%s/convert/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); + streamInfoResult.setHls(String.format("http://%s:%s/convert/%s/hls.m3u8", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); + streamInfoResult.setWs_hls(String.format("ws://%s:%s/convert/%s/hls.m3u8", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); + streamInfoResult.setFmp4(String.format("http://%s:%s/convert/%s.live.mp4", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); + streamInfoResult.setWs_fmp4(String.format("ws://%s:%s/convert/%s.live.mp4", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); + streamInfoResult.setTs(String.format("http://%s:%s/convert/%s.live.ts", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); + streamInfoResult.setWs_ts(String.format("ws://%s:%s/convert/%s.live.ts", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); + result.put("data", streamInfoResult); } + }else { + result.put("code", 1); + result.put("msg", "cover fail"); } - } else { - String flv = storager.getMediaInfo().getWanIp() + ":" + storager.getMediaInfo().getHttpPort() + "/rtp/" - + streamId + ".flv"; - streamInfo.setFlv("http://" + flv); - streamInfo.setWs_flv("ws://" + flv); - storager.startPlay(streamInfo); - } - - if (logger.isDebugEnabled()) { - logger.debug(String.format("璁惧棰勮 API璋冪敤锛宒eviceId锛�%s 锛宑hannelId锛�%s", deviceId, channelId)); - logger.debug("璁惧棰勮 API璋冪敤锛宻src锛�" + streamInfo.getSsrc() + ",ZLMedia streamId:" - + Integer.toHexString(Integer.parseInt(streamInfo.getSsrc()))); - } - - if (streamInfo != null) { - return new ResponseEntity<String>(JSON.toJSONString(streamInfo), HttpStatus.OK); - } else { - logger.warn("璁惧棰勮API璋冪敤澶辫触锛�"); - return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR); + return new ResponseEntity<String>( result.toJSONString(), HttpStatus.OK); } } - @PostMapping("/play/{ssrc}/stop") - public ResponseEntity<String> playStop(@PathVariable String ssrc) { + /** + * 缁撴潫杞爜 + * @param key + * @return + */ + @PostMapping("/play/convert/stop/{key}") + public ResponseEntity<String> playConvertStop(@PathVariable String key) { - cmder.streamByeCmd(ssrc); - StreamInfo streamInfo = storager.queryPlayBySSRC(ssrc); - if (streamInfo == null) - return new ResponseEntity<String>(HttpStatus.PAYMENT_REQUIRED); - storager.stopPlay(streamInfo); - if (logger.isDebugEnabled()) { - logger.debug(String.format("璁惧棰勮鍋滄API璋冪敤锛宻src锛�%s", ssrc)); - } + JSONObject jsonObject = zlmresTfulUtils.delFFmpegSource(key); + System.out.println(jsonObject); + JSONObject result = new JSONObject(); + if (jsonObject != null && jsonObject.getInteger("code") == 0) { + result.put("code", 0); + JSONObject data = jsonObject.getJSONObject("data"); + if (data != null && data.getBoolean("flag")) { + result.put("code", "0"); + result.put("msg", "success"); + }else { - if (ssrc != null) { - JSONObject json = new JSONObject(); - json.put("ssrc", ssrc); - return new ResponseEntity<String>(json.toString(), HttpStatus.OK); - } else { - logger.warn("璁惧棰勮鍋滄API璋冪敤澶辫触锛�"); - return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR); + } + }else { + result.put("code", 1); + result.put("msg", "delFFmpegSource fail"); } + return new ResponseEntity<String>( result.toJSONString(), HttpStatus.OK); } } -- Gitblit v1.8.0