Commit d21322a93258206eb910d7ac3a70a4812fc48cbc

Authored by 648540858
1 parent 01a619f9

优化国标级联录像预览

src/main/java/com/genersoft/iot/vmp/gb28181/bean/SDPInfo.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.bean;
  2 +
  3 +import javax.sdp.SessionDescription;
  4 +
  5 +public class SDPInfo {
  6 + private byte[] source;
  7 + private SessionDescription sdpSource;
  8 + private String sessionName;
  9 + private Long startTime;
  10 + private Long stopTime;
  11 + private String username;
  12 + private String address;
  13 + private String ssrc;
  14 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
... ... @@ -453,6 +453,7 @@ public class SIPCommander implements ISIPCommander {
453 453 subscribeKey.put("app", "rtp");
454 454 subscribeKey.put("stream", ssrcInfo.getStream());
455 455 subscribeKey.put("regist", true);
  456 + subscribeKey.put("schema", "rtmp");
456 457 subscribeKey.put("mediaServerId", mediaServerItem.getId());
457 458 logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString());
458 459 subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
... ... @@ -718,6 +719,7 @@ public class SIPCommander implements ISIPCommander {
718 719 if (ssrcTransaction != null) {
719 720 MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransaction.getMediaServerId());
720 721 mediaServerService.releaseSsrc(mediaServerItem, ssrcTransaction.getSsrc());
  722 + mediaServerService.closeRTPServer(deviceId, channelId, ssrcTransaction.getStream());
721 723 streamSession.remove(deviceId, channelId, ssrcTransaction.getStream());
722 724 }
723 725 } catch (SipException | ParseException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
... ... @@ -68,7 +68,7 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
68 68 */
69 69 @Override
70 70 public void process(RequestEvent evt) {
71   - logger.debug("ACK请求: {}", ((System.currentTimeMillis())));
  71 + logger.info("ACK请求: {}", ((System.currentTimeMillis())));
72 72 Dialog dialog = evt.getDialog();
73 73 if (dialog == null) return;
74 74 if (dialog.getState()== DialogState.CONFIRMED) {
... ... @@ -88,10 +88,6 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
88 88 streamInfo = new StreamInfo();
89 89 streamInfo.setApp(sendRtpItem.getApp());
90 90 streamInfo.setStream(sendRtpItem.getStreamId());
91   - }else {
92   - streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
93   - sendRtpItem.setStreamId(streamInfo.getStream());
94   - streamInfo.setApp("rtp");
95 91 }
96 92 redisCatchStorage.updateSendRTPSever(sendRtpItem);
97 93 logger.info(platformGbId);
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
... ... @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
2 2  
3 3 import com.genersoft.iot.vmp.common.StreamInfo;
4 4 import com.genersoft.iot.vmp.gb28181.bean.Device;
  5 +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
5 6 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
6 7 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
7 8 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
... ... @@ -90,29 +91,31 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
90 91 int totalReaderCount = zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId);
91 92 if (totalReaderCount == 0) {
92 93 logger.info(streamId + "无其它观看者,通知设备停止推流");
93   - cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId);
  94 + cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId, streamId);
94 95 }else if (totalReaderCount == -1){
95 96 logger.warn(streamId + " 查找其它观看者失败");
96 97 }
97 98 }
98 99 // 可能是设备主动停止
99 100 Device device = storager.queryVideoDeviceByChannelId(platformGbId);
100   - if (device != null) {
101   - if (sendRtpItem.isPlay()) {
102   - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId);
103   - if (streamInfo != null) {
104   - redisCatchStorage.stopPlay(streamInfo);
  101 + if (device != null) {
  102 + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId);
  103 + if (sendRtpItem != null) {
  104 + if (sendRtpItem.isPlay()) {
  105 + if (streamInfo != null) {
  106 + redisCatchStorage.stopPlay(streamInfo);
  107 + }
  108 + }else {
  109 + if (streamInfo != null) {
  110 + redisCatchStorage.stopPlayback(streamInfo);
  111 + }
105 112 }
106   - }else {
107   - StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(device.getDeviceId(), channelId);
108   - if (streamInfo != null) {
109   - redisCatchStorage.stopPlayback(streamInfo);
110   - }
111   - }
112 113  
113   - storager.stopPlay(device.getDeviceId(), channelId);
114   - mediaServerService.closeRTPServer(device, channelId, streamInfo.getStream());
  114 + storager.stopPlay(device.getDeviceId(), channelId);
  115 + mediaServerService.closeRTPServer(device.getDeviceId(), channelId, streamInfo.getStream());
  116 + }
115 117 }
  118 +
116 119 }
117 120 } catch (SipException e) {
118 121 e.printStackTrace();
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
... ... @@ -12,6 +12,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
12 12 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
13 13 import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
14 14 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
  15 +import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
15 16 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
16 17 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
17 18 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
... ... @@ -101,19 +102,12 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
101 102 @Override
102 103 public void process(RequestEvent evt) {
103 104 // Invite Request消息实现,此消息一般为级联消息,上级给下级发送请求视频指令
104   - Long startTimeForInvite = System.currentTimeMillis();
105 105 try {
106 106 Request request = evt.getRequest();
107 107 SipURI sipURI = (SipURI) request.getRequestURI();
108 108 String channelId = sipURI.getUser();
109   - String requesterId = null;
110   -
111   - FromHeader fromHeader = (FromHeader)request.getHeader(FromHeader.NAME);
  109 + String requesterId = SipUtils.getUserIdFromFromHeader(request);
112 110 CallIdHeader callIdHeader = (CallIdHeader)request.getHeader(CallIdHeader.NAME);
113   - AddressImpl address = (AddressImpl) fromHeader.getAddress();
114   - SipUri uri = (SipUri) address.getURI();
115   - requesterId = uri.getUser();
116   -
117 111 if (requesterId == null || channelId == null) {
118 112 logger.info("无法从FromHeader的Address中获取到平台id,返回400");
119 113 responseAck(evt, Response.BAD_REQUEST); // 参数不全, 发400,请求错误
... ... @@ -122,7 +116,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
122 116  
123 117 // 查询请求是否来自上级平台\设备
124 118 ParentPlatform platform = storager.queryParentPlatByServerGBId(requesterId);
125   - if (platform != null) {
  119 + if (platform == null) {
  120 + inviteFromDeviceHandle(evt, requesterId);
  121 + }else {
126 122 // 查询平台下是否有该通道
127 123 DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId);
128 124 GbStream gbStream = storager.queryStreamInParentPlatform(requesterId, channelId);
... ... @@ -141,7 +137,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
141 137 mediaServerItem = mediaServerService.getOne(mediaServerId);
142 138 if (mediaServerItem == null) {
143 139 logger.info("[ app={}, stream={} ]找不到zlm {},返回410",gbStream.getApp(), gbStream.getStream(), mediaServerId);
144   - responseAck(evt, Response.GONE, "media server not found");
  140 + responseAck(evt, Response.GONE);
145 141 return;
146 142 }
147 143 Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream());
... ... @@ -197,7 +193,6 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
197 193 // 查看是否支持PS 负载96
198 194 //String ip = null;
199 195 int port = -1;
200   - //boolean recvonly = false;
201 196 boolean mediaTransmissionTCP = false;
202 197 Boolean tcpActive = null;
203 198 for (Object description : mediaDescriptions) {
... ... @@ -233,7 +228,6 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
233 228 }
234 229 String username = sdp.getOrigin().getUsername();
235 230 String addressStr = sdp.getOrigin().getAddress();
236   - //String sessionName = sdp.getSessionName().getValue();
237 231 logger.info("[上级点播]用户:{}, 地址:{}:{}, ssrc:{}", username, addressStr, port, ssrc);
238 232 Device device = null;
239 233 // 通过 channel 和 gbStream 是否为null 值判断来源是直播流合适国标
... ... @@ -271,8 +265,10 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
271 265 Long finalStartTime = startTime;
272 266 Long finalStopTime = stopTime;
273 267 ZLMHttpHookSubscribe.Event hookEvent = (mediaServerItemInUSe, responseJSON)->{
274   - logger.info("[上级点播]收到下级开始点播订阅, {}/{}", sendRtpItem.getApp(), sendRtpItem.getStreamId());
275   - // if (sendRtpItem == null) return;
  268 + logger.info("[上级点播]下级已经开始推流。 回复200OK(SDP), {}/{}", sendRtpItem.getApp(), sendRtpItem.getStreamId());
  269 + // * 0 等待设备推流上来
  270 + // * 1 下级已经推流,等待上级平台回复ack
  271 + // * 2 推流中
276 272 sendRtpItem.setStatus(1);
277 273 redisCatchStorage.updateSendRTPSever(sendRtpItem);
278 274  
... ... @@ -301,9 +297,6 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
301 297 } catch (ParseException e) {
302 298 e.printStackTrace();
303 299 }
304   - if ("Playback".equals(sessionName) && responseJSON != null) {
305   - playService.onPublishHandlerForPlayBack(finalMediaServerItem, responseJSON, finalDevice.getDeviceId(), channelId, null);
306   - }
307 300 };
308 301 SipSubscribe.Event errorEvent = ((event) -> {
309 302 // 未知错误。直接转发设备点播的错误
... ... @@ -319,10 +312,29 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
319 312 });
320 313 if ("Playback".equals(sessionName)) {
321 314 sendRtpItem.setPlay(false);
322   - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, sendRtpItem.getSsrc(), true);
323 315 sendRtpItem.setStreamId(ssrc);
324 316 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
325   - commander.playbackStreamCmd(mediaServerItem, ssrcInfo, device, channelId, format.format(start), format.format(end), hookEvent, errorEvent);
  317 + playService.playBack(device.getDeviceId(), channelId, format.format(start), format.format(end),result -> {
  318 + if (result.getCode() != 0){
  319 + logger.warn("录像回放失败");
  320 + if (result.getEvent() != null) {
  321 + errorEvent.response(result.getEvent());
  322 + }
  323 + try {
  324 + responseAck(evt, Response.REQUEST_TIMEOUT);
  325 + } catch (SipException e) {
  326 + e.printStackTrace();
  327 + } catch (InvalidArgumentException e) {
  328 + e.printStackTrace();
  329 + } catch (ParseException e) {
  330 + e.printStackTrace();
  331 + }
  332 + }else {
  333 + if (result.getMediaServerItem() != null) {
  334 + hookEvent.response(result.getMediaServerItem(), result.getResponse());
  335 + }
  336 + }
  337 + });
326 338 }else {
327 339 sendRtpItem.setPlay(true);
328 340 StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId);
... ... @@ -333,7 +345,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
333 345 sendRtpItem.setPlay(false);
334 346 playService.play(mediaServerItem,device.getDeviceId(), channelId, hookEvent,errorEvent);
335 347 }else {
336   - sendRtpItem.setStreamId(streamInfo.getStreamId());
  348 + sendRtpItem.setStreamId(streamInfo.getStream());
337 349 hookEvent.response(mediaServerItem, null);
338 350 }
339 351 }
... ... @@ -379,72 +391,6 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
379 391 }
380 392 }
381 393  
382   - } else {
383   - // 非上级平台请求,查询是否设备请求(通常为接收语音广播的设备)
384   - Device device = redisCatchStorage.getDevice(requesterId);
385   - if (device != null) {
386   - logger.info("收到设备" + requesterId + "的语音广播Invite请求");
387   - responseAck(evt, Response.TRYING);
388   -
389   - String contentString = new String(request.getRawContent());
390   - // jainSip不支持y=字段, 移除移除以解析。
391   - String substring = contentString;
392   - String ssrc = "0000000404";
393   - int ssrcIndex = contentString.indexOf("y=");
394   - if (ssrcIndex > 0) {
395   - substring = contentString.substring(0, ssrcIndex);
396   - ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
397   - }
398   - ssrcIndex = substring.indexOf("f=");
399   - if (ssrcIndex > 0) {
400   - substring = contentString.substring(0, ssrcIndex);
401   - }
402   - SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring);
403   -
404   - // 获取支持的格式
405   - Vector mediaDescriptions = sdp.getMediaDescriptions(true);
406   - // 查看是否支持PS 负载96
407   - int port = -1;
408   - //boolean recvonly = false;
409   - boolean mediaTransmissionTCP = false;
410   - Boolean tcpActive = null;
411   - for (int i = 0; i < mediaDescriptions.size(); i++) {
412   - MediaDescription mediaDescription = (MediaDescription)mediaDescriptions.get(i);
413   - Media media = mediaDescription.getMedia();
414   -
415   - Vector mediaFormats = media.getMediaFormats(false);
416   - if (mediaFormats.contains("8")) {
417   - port = media.getMediaPort();
418   - String protocol = media.getProtocol();
419   - // 区分TCP发流还是udp, 当前默认udp
420   - if ("TCP/RTP/AVP".equals(protocol)) {
421   - String setup = mediaDescription.getAttribute("setup");
422   - if (setup != null) {
423   - mediaTransmissionTCP = true;
424   - if ("active".equals(setup)) {
425   - tcpActive = true;
426   - } else if ("passive".equals(setup)) {
427   - tcpActive = false;
428   - }
429   - }
430   - }
431   - break;
432   - }
433   - }
434   - if (port == -1) {
435   - logger.info("不支持的媒体格式,返回415");
436   - // 回复不支持的格式
437   - responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415
438   - return;
439   - }
440   - String username = sdp.getOrigin().getUsername();
441   - String addressStr = sdp.getOrigin().getAddress();
442   - logger.info("设备{}请求语音流,地址:{}:{},ssrc:{}", username, addressStr, port, ssrc);
443   -
444   - } else {
445   - logger.warn("来自无效设备/平台的请求");
446   - responseAck(evt, Response.BAD_REQUEST);
447   - }
448 394 }
449 395  
450 396 } catch (SipException | InvalidArgumentException | ParseException e) {
... ... @@ -457,4 +403,74 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
457 403 e.printStackTrace();
458 404 }
459 405 }
  406 +
  407 + public void inviteFromDeviceHandle(RequestEvent evt, String requesterId) throws InvalidArgumentException, ParseException, SipException, SdpException {
  408 +
  409 + // 非上级平台请求,查询是否设备请求(通常为接收语音广播的设备)
  410 + Device device = redisCatchStorage.getDevice(requesterId);
  411 + Request request = evt.getRequest();
  412 + if (device != null) {
  413 + logger.info("收到设备" + requesterId + "的语音广播Invite请求");
  414 + responseAck(evt, Response.TRYING);
  415 +
  416 + String contentString = new String(request.getRawContent());
  417 + // jainSip不支持y=字段, 移除移除以解析。
  418 + String substring = contentString;
  419 + String ssrc = "0000000404";
  420 + int ssrcIndex = contentString.indexOf("y=");
  421 + if (ssrcIndex > 0) {
  422 + substring = contentString.substring(0, ssrcIndex);
  423 + ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
  424 + }
  425 + ssrcIndex = substring.indexOf("f=");
  426 + if (ssrcIndex > 0) {
  427 + substring = contentString.substring(0, ssrcIndex);
  428 + }
  429 + SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring);
  430 +
  431 + // 获取支持的格式
  432 + Vector mediaDescriptions = sdp.getMediaDescriptions(true);
  433 + // 查看是否支持PS 负载96
  434 + int port = -1;
  435 + //boolean recvonly = false;
  436 + boolean mediaTransmissionTCP = false;
  437 + Boolean tcpActive = null;
  438 + for (int i = 0; i < mediaDescriptions.size(); i++) {
  439 + MediaDescription mediaDescription = (MediaDescription)mediaDescriptions.get(i);
  440 + Media media = mediaDescription.getMedia();
  441 +
  442 + Vector mediaFormats = media.getMediaFormats(false);
  443 + if (mediaFormats.contains("8")) {
  444 + port = media.getMediaPort();
  445 + String protocol = media.getProtocol();
  446 + // 区分TCP发流还是udp, 当前默认udp
  447 + if ("TCP/RTP/AVP".equals(protocol)) {
  448 + String setup = mediaDescription.getAttribute("setup");
  449 + if (setup != null) {
  450 + mediaTransmissionTCP = true;
  451 + if ("active".equals(setup)) {
  452 + tcpActive = true;
  453 + } else if ("passive".equals(setup)) {
  454 + tcpActive = false;
  455 + }
  456 + }
  457 + }
  458 + break;
  459 + }
  460 + }
  461 + if (port == -1) {
  462 + logger.info("不支持的媒体格式,返回415");
  463 + // 回复不支持的格式
  464 + responseAck(evt, Response.UNSUPPORTED_MEDIA_TYPE); // 不支持的格式,发415
  465 + return;
  466 + }
  467 + String username = sdp.getOrigin().getUsername();
  468 + String addressStr = sdp.getOrigin().getAddress();
  469 + logger.info("设备{}请求语音流,地址:{}:{},ssrc:{}", username, addressStr, port, ssrc);
  470 +
  471 + } else {
  472 + logger.warn("来自无效设备/平台的请求");
  473 + responseAck(evt, Response.BAD_REQUEST);
  474 + }
  475 + }
460 476 }
... ...
src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java
... ... @@ -48,7 +48,7 @@ public interface IMediaServerService {
48 48  
49 49 SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean isPlayback);
50 50  
51   - void closeRTPServer(Device device, String channelId, String ssrc);
  51 + void closeRTPServer(String deviceId, String channelId, String ssrc);
52 52  
53 53 void clearRTPServer(MediaServerItem mediaServerItem);
54 54  
... ...
src/main/java/com/genersoft/iot/vmp/service/bean/PlayBackCallback.java
1 1 package com.genersoft.iot.vmp.service.bean;
2 2  
3 3 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
  4 +import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
4 5  
5 6 public interface PlayBackCallback {
6 7  
7   - void call(RequestMessage msg);
  8 + void call(PlayBackResult<RequestMessage> msg);
8 9  
9 10 }
... ...
src/main/java/com/genersoft/iot/vmp/service/bean/PlayBackResult.java 0 → 100644
  1 +package com.genersoft.iot.vmp.service.bean;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
  5 +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
  6 +
  7 +import javax.sip.RequestEvent;
  8 +
  9 +public class PlayBackResult<T> {
  10 + private int code;
  11 + private T data;
  12 + private MediaServerItem mediaServerItem;
  13 + private JSONObject response;
  14 + private SipSubscribe.EventResult event;
  15 +
  16 + public int getCode() {
  17 + return code;
  18 + }
  19 +
  20 + public void setCode(int code) {
  21 + this.code = code;
  22 + }
  23 +
  24 + public T getData() {
  25 + return data;
  26 + }
  27 +
  28 + public void setData(T data) {
  29 + this.data = data;
  30 + }
  31 +
  32 + public MediaServerItem getMediaServerItem() {
  33 + return mediaServerItem;
  34 + }
  35 +
  36 + public void setMediaServerItem(MediaServerItem mediaServerItem) {
  37 + this.mediaServerItem = mediaServerItem;
  38 + }
  39 +
  40 + public JSONObject getResponse() {
  41 + return response;
  42 + }
  43 +
  44 + public void setResponse(JSONObject response) {
  45 + this.response = response;
  46 + }
  47 +
  48 + public SipSubscribe.EventResult getEvent() {
  49 + return event;
  50 + }
  51 +
  52 + public void setEvent(SipSubscribe.EventResult event) {
  53 + this.event = event;
  54 + }
  55 +}
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
... ... @@ -160,16 +160,16 @@ public class MediaServerServiceImpl implements IMediaServerService {
160 160 }
161 161  
162 162 @Override
163   - public void closeRTPServer(Device device, String channelId, String stream) {
164   - String mediaServerId = streamSession.getMediaServerId(device.getDeviceId(), channelId, stream);
165   - String ssrc = streamSession.getSSRC(device.getDeviceId(), channelId, stream);
  163 + public void closeRTPServer(String deviceId, String channelId, String stream) {
  164 + String mediaServerId = streamSession.getMediaServerId(deviceId, channelId, stream);
  165 + String ssrc = streamSession.getSSRC(deviceId, channelId, stream);
166 166 MediaServerItem mediaServerItem = this.getOne(mediaServerId);
167 167 if (mediaServerItem != null) {
168   - String streamId = String.format("%s_%s", device.getDeviceId(), channelId);
  168 + String streamId = String.format("%s_%s", deviceId, channelId);
169 169 zlmrtpServerFactory.closeRTPServer(mediaServerItem, streamId);
170 170 releaseSsrc(mediaServerItem, ssrc);
171 171 }
172   - streamSession.remove(device.getDeviceId(), channelId, stream);
  172 + streamSession.remove(deviceId, channelId, stream);
173 173 }
174 174  
175 175 @Override
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
... ... @@ -17,6 +17,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
17 17 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
18 18 import com.genersoft.iot.vmp.service.IMediaServerService;
19 19 import com.genersoft.iot.vmp.service.bean.PlayBackCallback;
  20 +import com.genersoft.iot.vmp.service.bean.PlayBackResult;
20 21 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
21 22 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
22 23 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
... ... @@ -115,11 +116,8 @@ public class PlayServiceImpl implements IPlayService {
115 116 msg.setData(wvpResult);
116 117 // 点播超时回复BYE
117 118 cmder.streamByeCmd(device.getDeviceId(), channelId, streamInfo.getStream());
118   - // 释放rtpserver
119   - mediaServerService.closeRTPServer(playResult.getDevice(), channelId, streamInfo.getStream());
120 119 // 回复之前所有的点播请求
121 120 resultHolder.invokeAllResult(msg);
122   - // TODO 释放ssrc
123 121 });
124 122 result.onCompletion(()->{
125 123 // 点播结束时调用截图接口
... ... @@ -173,7 +171,10 @@ public class PlayServiceImpl implements IPlayService {
173 171 WVPResult wvpResult = new WVPResult();
174 172 wvpResult.setCode(-1);
175 173 // 点播返回sip错误
176   - mediaServerService.closeRTPServer(playResult.getDevice(), channelId, ssrcInfo.getStream());
  174 + mediaServerService.closeRTPServer(playResult.getDevice().getDeviceId(), channelId, ssrcInfo.getStream());
  175 + // 释放ssrc
  176 + mediaServerService.releaseSsrc(mediaServerItem, ssrcInfo.getSsrc());
  177 + streamSession.remove(deviceId, channelId, ssrcInfo.getStream());
177 178 wvpResult.setMsg(String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg));
178 179 msg.setData(wvpResult);
179 180 resultHolder.invokeAllResult(msg);
... ... @@ -222,7 +223,10 @@ public class PlayServiceImpl implements IPlayService {
222 223 logger.info("收到订阅消息: " + response.toJSONString());
223 224 onPublishHandlerForPlay(mediaServerItemInuse, response, deviceId, channelId, uuid);
224 225 }, (event) -> {
225   - mediaServerService.closeRTPServer(playResult.getDevice(), channelId, ssrcInfo.getStream());
  226 + mediaServerService.closeRTPServer(playResult.getDevice().getDeviceId(), channelId, ssrcInfo.getStream());
  227 + // 释放ssrc
  228 + mediaServerService.releaseSsrc(mediaServerItem, ssrcInfo.getSsrc());
  229 + streamSession.remove(deviceId, channelId, ssrcInfo.getStream());
226 230 WVPResult wvpResult = new WVPResult();
227 231 wvpResult.setCode(-1);
228 232 wvpResult.setMsg(String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg));
... ... @@ -240,7 +244,7 @@ public class PlayServiceImpl implements IPlayService {
240 244 RequestMessage msg = new RequestMessage();
241 245 msg.setId(uuid);
242 246 msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId);
243   - StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId);
  247 + StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId);
244 248 if (streamInfo != null) {
245 249 DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId);
246 250 if (deviceChannel != null) {
... ... @@ -298,9 +302,12 @@ public class PlayServiceImpl implements IPlayService {
298 302 RequestMessage msg = new RequestMessage();
299 303 msg.setId(uuid);
300 304 msg.setKey(key);
  305 + PlayBackResult<RequestMessage> playBackResult = new PlayBackResult<>();
301 306 result.onTimeout(()->{
302 307 msg.setData("回放超时");
303   - callback.call(msg);
  308 + playBackResult.setCode(-1);
  309 + playBackResult.setData(msg);
  310 + callback.call(playBackResult);
304 311 });
305 312 cmder.playbackStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, (MediaServerItem mediaServerItem, JSONObject response) -> {
306 313 logger.info("收到订阅消息: " + response.toJSONString());
... ... @@ -308,15 +315,24 @@ public class PlayServiceImpl implements IPlayService {
308 315 if (streamInfo == null) {
309 316 logger.warn("设备回放API调用失败!");
310 317 msg.setData("设备回放API调用失败!");
311   - callback.call(msg);
  318 + playBackResult.setCode(-1);
  319 + playBackResult.setData(msg);
  320 + callback.call(playBackResult);
312 321 return;
313 322 }
314 323 redisCatchStorage.startPlayback(streamInfo);
315 324 msg.setData(JSON.toJSONString(streamInfo));
316   - callback.call(msg);
  325 + playBackResult.setCode(0);
  326 + playBackResult.setData(msg);
  327 + playBackResult.setMediaServerItem(mediaServerItem);
  328 + playBackResult.setResponse(response);
  329 + callback.call(playBackResult);
317 330 }, event -> {
318 331 msg.setData(String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg));
319   - callback.call(msg);
  332 + playBackResult.setCode(-1);
  333 + playBackResult.setData(msg);
  334 + playBackResult.setEvent(event);
  335 + callback.call(playBackResult);
320 336 });
321 337 return result;
322 338 }
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
... ... @@ -129,7 +129,6 @@ public class PlayController {
129 129 //Response response = event.getResponse();
130 130 msg.setData(String.format("success"));
131 131 resultHolder.invokeAllResult(msg);
132   - mediaServerService.closeRTPServer(device, channelId, streamInfo.getStream());
133 132 });
134 133  
135 134 if (deviceId != null || channelId != null) {
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java
... ... @@ -77,8 +77,8 @@ public class PlaybackController {
77 77 logger.debug(String.format("设备回放 API调用,deviceId:%s ,channelId:%s", deviceId, channelId));
78 78 }
79 79  
80   - DeferredResult<ResponseEntity<String>> result = playService.playBack(deviceId, channelId, startTime, endTime, msg->{
81   - resultHolder.invokeResult(msg);
  80 + DeferredResult<ResponseEntity<String>> result = playService.playBack(deviceId, channelId, startTime, endTime, wvpResult->{
  81 + resultHolder.invokeResult(wvpResult.getData());
82 82 });
83 83  
84 84 return result;
... ...