Commit bfd1628d5b6e753091b0aa702a520b08cc64cc76
1 parent
1ec6c450
修复重复调用open rtp server 的bug
增加对rtp server开启释放的统一管理
Showing
6 changed files
with
38 additions
and
71 deletions
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
| ... | ... | @@ -213,4 +213,11 @@ public interface ISIPCommander { |
| 213 | 213 | * @param device 视频设备 |
| 214 | 214 | */ |
| 215 | 215 | boolean mobilePostitionQuery(Device device); |
| 216 | + | |
| 217 | + /** | |
| 218 | + * 释放rtpserver | |
| 219 | + * @param device | |
| 220 | + * @param channelId | |
| 221 | + */ | |
| 222 | + void closeRTPServer(Device device, String channelId); | |
| 216 | 223 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
| ... | ... | @@ -8,7 +8,6 @@ import javax.sip.ClientTransaction; |
| 8 | 8 | import javax.sip.Dialog; |
| 9 | 9 | import javax.sip.InvalidArgumentException; |
| 10 | 10 | import javax.sip.SipException; |
| 11 | -import javax.sip.SipFactory; | |
| 12 | 11 | import javax.sip.SipProvider; |
| 13 | 12 | import javax.sip.TransactionDoesNotExistException; |
| 14 | 13 | import javax.sip.address.SipURI; |
| ... | ... | @@ -16,11 +15,10 @@ import javax.sip.header.ViaHeader; |
| 16 | 15 | import javax.sip.message.Request; |
| 17 | 16 | |
| 18 | 17 | import com.alibaba.fastjson.JSONObject; |
| 19 | -import com.genersoft.iot.vmp.common.StreamInfo; | |
| 20 | 18 | import com.genersoft.iot.vmp.conf.MediaServerConfig; |
| 21 | 19 | import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; |
| 22 | 20 | import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; |
| 23 | -import com.genersoft.iot.vmp.media.zlm.ZLMUtils; | |
| 21 | +import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; | |
| 24 | 22 | import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
| 25 | 23 | import org.springframework.beans.factory.annotation.Autowired; |
| 26 | 24 | import org.springframework.beans.factory.annotation.Qualifier; |
| ... | ... | @@ -63,7 +61,7 @@ public class SIPCommander implements ISIPCommander { |
| 63 | 61 | private SipProvider udpSipProvider; |
| 64 | 62 | |
| 65 | 63 | @Autowired |
| 66 | - private ZLMUtils zlmUtils; | |
| 64 | + private ZLMRTPServerFactory zlmrtpServerFactory; | |
| 67 | 65 | |
| 68 | 66 | @Value("${media.rtp.enable}") |
| 69 | 67 | private boolean rtpEnable; |
| ... | ... | @@ -288,7 +286,7 @@ public class SIPCommander implements ISIPCommander { |
| 288 | 286 | String mediaPort = null; |
| 289 | 287 | // 使用动态udp端口 |
| 290 | 288 | if (rtpEnable) { |
| 291 | - mediaPort = zlmUtils.getNewRTPPort(streamId) + ""; | |
| 289 | + mediaPort = zlmrtpServerFactory.createRTPServer(streamId) + ""; | |
| 292 | 290 | }else { |
| 293 | 291 | mediaPort = mediaInfo.getRtpProxyPort(); |
| 294 | 292 | } |
| ... | ... | @@ -383,7 +381,7 @@ public class SIPCommander implements ISIPCommander { |
| 383 | 381 | String mediaPort = null; |
| 384 | 382 | // 使用动态udp端口 |
| 385 | 383 | if (rtpEnable) { |
| 386 | - mediaPort = zlmUtils.getNewRTPPort(streamId) + ""; | |
| 384 | + mediaPort = zlmrtpServerFactory.createRTPServer(streamId) + ""; | |
| 387 | 385 | }else { |
| 388 | 386 | mediaPort = mediaInfo.getRtpProxyPort(); |
| 389 | 387 | } |
| ... | ... | @@ -459,6 +457,7 @@ public class SIPCommander implements ISIPCommander { |
| 459 | 457 | } |
| 460 | 458 | dialog.sendRequest(clientTransaction); |
| 461 | 459 | streamSession.remove(streamId); |
| 460 | + zlmrtpServerFactory.closeRTPServer(streamId); | |
| 462 | 461 | } catch (TransactionDoesNotExistException e) { |
| 463 | 462 | e.printStackTrace(); |
| 464 | 463 | } catch (SipException e) { |
| ... | ... | @@ -701,4 +700,11 @@ public class SIPCommander implements ISIPCommander { |
| 701 | 700 | } |
| 702 | 701 | |
| 703 | 702 | |
| 703 | + @Override | |
| 704 | + public void closeRTPServer(Device device, String channelId) { | |
| 705 | + if (rtpEnable) { | |
| 706 | + String streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId); | |
| 707 | + zlmrtpServerFactory.closeRTPServer(streamId); | |
| 708 | + } | |
| 709 | + } | |
| 704 | 710 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java
| ... | ... | @@ -116,4 +116,8 @@ public class ZLMRESTfulUtils { |
| 116 | 116 | public JSONObject openRtpServer(Map<String, Object> param){ |
| 117 | 117 | return sendPost("openRtpServer",param); |
| 118 | 118 | } |
| 119 | + | |
| 120 | + public JSONObject closeRtpServer(Map<String, Object> param) { | |
| 121 | + return sendPost("closeRtpServer",param); | |
| 122 | + } | |
| 119 | 123 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMUtils.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.media.zlm; | |
| 2 | - | |
| 3 | -import com.alibaba.fastjson.JSONObject; | |
| 4 | -import org.springframework.beans.factory.annotation.Autowired; | |
| 5 | -import org.springframework.beans.factory.annotation.Value; | |
| 6 | -import org.springframework.stereotype.Component; | |
| 7 | - | |
| 8 | -import java.util.HashMap; | |
| 9 | -import java.util.Map; | |
| 10 | - | |
| 11 | -@Component | |
| 12 | -public class ZLMUtils { | |
| 13 | - | |
| 14 | - @Value("${media.rtp.udpPortRange}") | |
| 15 | - private String udpPortRange; | |
| 16 | - | |
| 17 | - @Autowired | |
| 18 | - private ZLMRESTfulUtils zlmresTfulUtils; | |
| 19 | - | |
| 20 | - private int[] udpPortRangeArray = new int[2]; | |
| 21 | - | |
| 22 | - private int currentPort = 0; | |
| 23 | - | |
| 24 | - public int getNewRTPPort(String streamId) { | |
| 25 | -// String streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase(); | |
| 26 | - Map<String, Object> param = new HashMap<>(); | |
| 27 | - int newPort = getPortFromUdpPortRange(); | |
| 28 | - param.put("port", newPort); | |
| 29 | - param.put("enable_tcp", 1); | |
| 30 | - param.put("stream_id", streamId); | |
| 31 | - JSONObject jsonObject = zlmresTfulUtils.openRtpServer(param); | |
| 32 | - if (jsonObject != null && jsonObject.getInteger("code") == 0) { | |
| 33 | - return newPort; | |
| 34 | - } else { | |
| 35 | - return getNewRTPPort(streamId); | |
| 36 | - } | |
| 37 | - } | |
| 38 | - | |
| 39 | - private int getPortFromUdpPortRange() { | |
| 40 | - if (currentPort == 0) { | |
| 41 | - String[] udpPortRangeStrArray = udpPortRange.split(","); | |
| 42 | - udpPortRangeArray[0] = Integer.parseInt(udpPortRangeStrArray[0]); | |
| 43 | - udpPortRangeArray[1] = Integer.parseInt(udpPortRangeStrArray[1]); | |
| 44 | - } | |
| 45 | - | |
| 46 | - if (currentPort == 0 || currentPort++ > udpPortRangeArray[1]) { | |
| 47 | - currentPort = udpPortRangeArray[0]; | |
| 48 | - return udpPortRangeArray[0]; | |
| 49 | - } else { | |
| 50 | - if (currentPort % 2 == 1) { | |
| 51 | - currentPort++; | |
| 52 | - } | |
| 53 | - return currentPort++; | |
| 54 | - } | |
| 55 | - } | |
| 56 | -} |
src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java
| ... | ... | @@ -7,6 +7,7 @@ import com.genersoft.iot.vmp.conf.MediaServerConfig; |
| 7 | 7 | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
| 8 | 8 | import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; |
| 9 | 9 | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; |
| 10 | +import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; | |
| 10 | 11 | import com.genersoft.iot.vmp.vmanager.service.IPlayService; |
| 11 | 12 | import org.slf4j.Logger; |
| 12 | 13 | import org.slf4j.LoggerFactory; |
| ... | ... | @@ -62,14 +63,7 @@ public class PlayController { |
| 62 | 63 | |
| 63 | 64 | UUID uuid = UUID.randomUUID(); |
| 64 | 65 | DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(); |
| 65 | - // 超时处理 | |
| 66 | - result.onTimeout(()->{ | |
| 67 | - logger.warn(String.format("设备点播超时,deviceId:%s ,channelId:%s", deviceId, channelId)); | |
| 68 | - RequestMessage msg = new RequestMessage(); | |
| 69 | - msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid); | |
| 70 | - msg.setData("Timeout"); | |
| 71 | - resultHolder.invokeResult(msg); | |
| 72 | - }); | |
| 66 | + | |
| 73 | 67 | // 录像查询以channelId作为deviceId查询 |
| 74 | 68 | resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result); |
| 75 | 69 | |
| ... | ... | @@ -89,13 +83,23 @@ public class PlayController { |
| 89 | 83 | resultHolder.invokeResult(msg); |
| 90 | 84 | } else { |
| 91 | 85 | storager.stopPlay(streamInfo); |
| 92 | - // TODO playStreamCmd 超时处理 | |
| 93 | 86 | cmder.playStreamCmd(device, channelId, (JSONObject response) -> { |
| 94 | 87 | logger.info("收到订阅消息: " + response.toJSONString()); |
| 95 | 88 | playService.onPublishHandlerForPlay(response, deviceId, channelId, uuid.toString()); |
| 96 | 89 | }); |
| 97 | 90 | } |
| 98 | 91 | } |
| 92 | + | |
| 93 | + // 超时处理 | |
| 94 | + result.onTimeout(()->{ | |
| 95 | + logger.warn(String.format("设备点播超时,deviceId:%s ,channelId:%s", deviceId, channelId)); | |
| 96 | + // 释放rtpserver | |
| 97 | + cmder.closeRTPServer(device, channelId); | |
| 98 | + RequestMessage msg = new RequestMessage(); | |
| 99 | + msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid); | |
| 100 | + msg.setData("Timeout"); | |
| 101 | + resultHolder.invokeResult(msg); | |
| 102 | + }); | |
| 99 | 103 | return result; |
| 100 | 104 | } |
| 101 | 105 | ... | ... |
src/main/java/com/genersoft/iot/vmp/web/ApiStreamController.java
| ... | ... | @@ -86,6 +86,8 @@ public class ApiStreamController { |
| 86 | 86 | JSONObject result = new JSONObject(); |
| 87 | 87 | result.put("error","timeout"); |
| 88 | 88 | resultDeferredResult.setResult(result); |
| 89 | + | |
| 90 | + // 清理RTP server | |
| 89 | 91 | }); |
| 90 | 92 | |
| 91 | 93 | DeviceChannel deviceChannel = storager.queryChannel(serial, code); | ... | ... |