Commit 0c10e8d9d3ca01fb31f632560f6089f5d2b1d585

Authored by 648540858
1 parent 0eba7c40

优化info消息的cseq计数

src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
... ... @@ -56,6 +56,8 @@ public class VideoManagerConstants {
56 56  
57 57 public static final String MEDIA_TRANSACTION_USED_PREFIX = "VMP_MEDIA_TRANSACTION_";
58 58  
  59 + public static final String SIP_CSEQ_PREFIX = "VMP_SIP_CSEQ_";
  60 +
59 61 //************************** redis 消息*********************************
60 62 public static final String WVP_MSG_STREAM_CHANGE_PREFIX = "WVP_MSG_STREAM_CHANGE_";
61 63  
... ...
src/main/java/com/genersoft/iot/vmp/conf/runner/SipDeviceRunner.java
1 1 package com.genersoft.iot.vmp.conf.runner;
2 2  
  3 +import com.genersoft.iot.vmp.common.VideoManagerConstants;
  4 +import com.genersoft.iot.vmp.conf.UserSetup;
3 5 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
4 6 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
5 7 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -23,6 +25,9 @@ public class SipDeviceRunner implements CommandLineRunner {
23 25 @Autowired
24 26 private IRedisCatchStorage redisCatchStorage;
25 27  
  28 + @Autowired
  29 + private UserSetup userSetup;
  30 +
26 31 @Override
27 32 public void run(String... args) throws Exception {
28 33 // 读取redis没有心跳信息的则设置为离线,等收到下次心跳设置为在线
... ... @@ -32,7 +37,8 @@ public class SipDeviceRunner implements CommandLineRunner {
32 37 for (String deviceId : onlineForAll) {
33 38 storager.online(deviceId);
34 39 }
35   -
  40 + // 重置cseq计数
  41 + redisCatchStorage.resetAllCSEQ();
36 42 // TODO 查询在线设备那些开启了订阅,为设备开启定时的目录订阅
37 43 }
38 44 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
... ... @@ -14,7 +14,7 @@ import javax.sip.message.Request;
14 14  
15 15 import com.genersoft.iot.vmp.common.StreamInfo;
16 16 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
17   -import com.genersoft.iot.vmp.vmanager.gb28181.session.InfoCseqCache;
  17 +import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
18 18 import org.springframework.beans.factory.annotation.Autowired;
19 19 import org.springframework.stereotype.Component;
20 20  
... ... @@ -36,6 +36,9 @@ public class SIPRequestHeaderProvider {
36 36 private SipFactory sipFactory;
37 37  
38 38 @Autowired
  39 + private IRedisCatchStorage redisCatchStorage;
  40 +
  41 + @Autowired
39 42 private VideoStreamSessionManager streamSession;
40 43  
41 44 public Request createMessageRequest(Device device, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
... ... @@ -195,6 +198,7 @@ public class SIPRequestHeaderProvider {
195 198  
196 199 // Forwards
197 200 MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
  201 +
198 202 // ceq
199 203 CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(1L, Request.SUBSCRIBE);
200 204  
... ... @@ -218,7 +222,7 @@ public class SIPRequestHeaderProvider {
218 222 return request;
219 223 }
220 224  
221   - public Request createInfoRequest(Device device, StreamInfo streamInfo, String content)
  225 + public Request createInfoRequest(Device device, StreamInfo streamInfo, String content, Long cseq)
222 226 throws PeerUnavailableException, ParseException, InvalidArgumentException {
223 227 Request request = null;
224 228 Dialog dialog = streamSession.getDialog(streamInfo.getDeviceID(), streamInfo.getChannelId());
... ... @@ -247,10 +251,12 @@ public class SIPRequestHeaderProvider {
247 251  
248 252 // Forwards
249 253 MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
250   -
  254 + if (cseq == null) {
  255 + cseq = redisCatchStorage.getCSEQ(Request.INFO);
  256 + }
251 257 // ceq
252 258 CSeqHeader cSeqHeader = sipFactory.createHeaderFactory()
253   - .createCSeqHeader(InfoCseqCache.CSEQCACHE.get(streamInfo.getStreamId()), Request.INFO);
  259 + .createCSeqHeader(cseq, Request.INFO);
254 260  
255 261 request = sipFactory.createMessageFactory().createRequest(requestLine, Request.INFO, callIdHeader, cSeqHeader,
256 262 fromHeader, toHeader, viaHeaders, maxForwards);
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
... ... @@ -18,7 +18,6 @@ import com.genersoft.iot.vmp.service.IMediaServerService;
18 18 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
19 19 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
20 20 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
21   -import com.genersoft.iot.vmp.vmanager.gb28181.session.InfoCseqCache;
22 21 import gov.nist.javax.sip.SipProviderImpl;
23 22 import gov.nist.javax.sip.SipStackImpl;
24 23 import gov.nist.javax.sip.message.SIPRequest;
... ... @@ -1553,12 +1552,12 @@ public class SIPCommander implements ISIPCommander {
1553 1552 @Override
1554 1553 public void playPauseCmd(Device device, StreamInfo streamInfo) {
1555 1554 try {
1556   -
  1555 + Long cseq = redisCatchStorage.getCSEQ(Request.INFO);
1557 1556 StringBuffer content = new StringBuffer(200);
1558 1557 content.append("PAUSE RTSP/1.0\r\n");
1559   - content.append("CSeq: " + InfoCseqCache.CSEQCACHE.get(streamInfo.getStreamId()) + "\r\n");
  1558 + content.append("CSeq: " + cseq + "\r\n");
1560 1559 content.append("PauseTime: now\r\n");
1561   - Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString());
  1560 + Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString(), cseq);
1562 1561 logger.info(request.toString());
1563 1562 ClientTransaction clientTransaction = null;
1564 1563 if ("TCP".equals(device.getTransport())) {
... ... @@ -1581,11 +1580,12 @@ public class SIPCommander implements ISIPCommander {
1581 1580 @Override
1582 1581 public void playResumeCmd(Device device, StreamInfo streamInfo) {
1583 1582 try {
  1583 + Long cseq = redisCatchStorage.getCSEQ(Request.INFO);
1584 1584 StringBuffer content = new StringBuffer(200);
1585 1585 content.append("PLAY RTSP/1.0\r\n");
1586   - content.append("CSeq: " + InfoCseqCache.CSEQCACHE.get(streamInfo.getStreamId()) + "\r\n");
  1586 + content.append("CSeq: " + cseq + "\r\n");
1587 1587 content.append("Range: npt=now-\r\n");
1588   - Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString());
  1588 + Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString(), cseq);
1589 1589 logger.info(request.toString());
1590 1590 ClientTransaction clientTransaction = null;
1591 1591 if ("TCP".equals(device.getTransport())) {
... ... @@ -1607,12 +1607,13 @@ public class SIPCommander implements ISIPCommander {
1607 1607 @Override
1608 1608 public void playSeekCmd(Device device, StreamInfo streamInfo, long seekTime) {
1609 1609 try {
  1610 + Long cseq = redisCatchStorage.getCSEQ(Request.INFO);
1610 1611 StringBuffer content = new StringBuffer(200);
1611 1612 content.append("PLAY RTSP/1.0\r\n");
1612   - content.append("CSeq: " + InfoCseqCache.CSEQCACHE.get(streamInfo.getStreamId()) + "\r\n");
  1613 + content.append("CSeq: " + cseq + "\r\n");
1613 1614 content.append("Range: npt=" + Math.abs(seekTime) + "-\r\n");
1614 1615  
1615   - Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString());
  1616 + Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString(), cseq);
1616 1617 logger.info(request.toString());
1617 1618 ClientTransaction clientTransaction = null;
1618 1619 if ("TCP".equals(device.getTransport())) {
... ... @@ -1634,11 +1635,12 @@ public class SIPCommander implements ISIPCommander {
1634 1635 @Override
1635 1636 public void playSpeedCmd(Device device, StreamInfo streamInfo, Double speed) {
1636 1637 try {
  1638 + Long cseq = redisCatchStorage.getCSEQ(Request.INFO);
1637 1639 StringBuffer content = new StringBuffer(200);
1638 1640 content.append("PLAY RTSP/1.0\r\n");
1639   - content.append("CSeq: " + InfoCseqCache.CSEQCACHE.get(streamInfo.getStreamId()) + "\r\n");
  1641 + content.append("CSeq: " + cseq + "\r\n");
1640 1642 content.append("Scale: " + String.format("%.1f",speed) + "\r\n");
1641   - Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString());
  1643 + Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString(), cseq);
1642 1644 logger.info(request.toString());
1643 1645 ClientTransaction clientTransaction = null;
1644 1646 if ("TCP".equals(device.getTransport())) {
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java
... ... @@ -89,7 +89,7 @@ public class ZLMRunner implements CommandLineRunner {
89 89 });
90 90  
91 91 // 获取zlm信息
92   - logger.info("等待默认zlm接入...");
  92 + logger.info("[zlm接入]等待默认zlm中...");
93 93  
94 94 // 获取所有的zlm, 并开启主动连接
95 95 List<MediaServerItem> all = mediaServerService.getAllFromDatabase();
... ...
src/main/java/com/genersoft/iot/vmp/service/bean/CatalogSubscribeTask.java
... ... @@ -25,24 +25,28 @@ public class CatalogSubscribeTask implements Runnable{
25 25 sipCommander.catalogSubscribe(device, eventResult -> {
26 26 ResponseEvent event = (ResponseEvent) eventResult.event;
27 27 Element rootElement = null;
28   - try {
29   - rootElement = XmlUtil.getRootElement(event.getResponse().getRawContent(), "gb2312");
30   - } catch (DocumentException e) {
31   - e.printStackTrace();
32   - }
33   - Element resultElement = rootElement.element("Result");
34   - String result = resultElement.getText();
35   - if (result.toUpperCase().equals("OK")){
36   - // 成功
37   - logger.info("目录订阅成功: {}", device.getDeviceId());
  28 + if (event.getResponse().getRawContent() != null) {
  29 + try {
  30 + rootElement = XmlUtil.getRootElement(event.getResponse().getRawContent(), "gb2312");
  31 + } catch (DocumentException e) {
  32 + e.printStackTrace();
  33 + }
  34 + Element resultElement = rootElement.element("Result");
  35 + String result = resultElement.getText();
  36 + if (result.toUpperCase().equals("OK")){
  37 + // 成功
  38 + logger.info("[目录订阅]成功: {}", device.getDeviceId());
  39 + }else {
  40 + // 失败
  41 + logger.info("[目录订阅]失败: {}-{}", device.getDeviceId(), result);
  42 + }
38 43 }else {
39   - // 失败
40   - logger.info("目录订阅失败: {}-{}", device.getDeviceId(), result);
  44 + // 成功
  45 + logger.info("[目录订阅]成功: {}", device.getDeviceId());
41 46 }
42   -
43 47 },eventResult -> {
44 48 // 失败
45   - logger.warn("目录订阅失败: {}-信令发送失败", device.getDeviceId());
  49 + logger.warn("[目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
46 50 });
47 51 }
48 52 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
... ... @@ -51,6 +51,8 @@ public class DeviceServiceImpl implements IDeviceService {
51 51 dynamicTask.stopCron(device.getDeviceId());
52 52 device.setSubscribeCycleForCatalog(0);
53 53 sipCommander.catalogSubscribe(device, null, null);
  54 + // 清空cseq计数
  55 +
54 56 return true;
55 57 }
56 58 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
... ... @@ -83,7 +83,7 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
83 83 */
84 84 @Override
85 85 public void run(String... args) throws Exception {
86   - logger.info("Media Server 缓存初始化");
  86 + logger.info("[缓存初始化] Media Server ");
87 87 List<MediaServerItem> mediaServerItemList = mediaServerMapper.queryAll();
88 88 for (MediaServerItem mediaServerItem : mediaServerItemList) {
89 89 if (StringUtils.isEmpty(mediaServerItem.getId())) {
... ...
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
... ... @@ -15,6 +15,14 @@ import java.util.Map;
15 15 public interface IRedisCatchStorage {
16 16  
17 17 /**
  18 + * 计数器。为cseq进行计数
  19 + *
  20 + * @param method sip 方法
  21 + * @return
  22 + */
  23 + Long getCSEQ(String method);
  24 +
  25 + /**
18 26 * 开始播放时将流存入
19 27 *
20 28 * @param stream 流信息
... ... @@ -181,4 +189,6 @@ public interface IRedisCatchStorage {
181 189 * 获取Device
182 190 */
183 191 Device getDevice(String deviceId);
  192 +
  193 + void resetAllCSEQ();
184 194 }
... ...
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
... ... @@ -36,6 +36,28 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
36 36  
37 37 private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
38 38  
  39 + @Override
  40 + public Long getCSEQ(String method) {
  41 + String key = VideoManagerConstants.SIP_CSEQ_PREFIX + userSetup.getServerId() + "_" + method;
  42 +
  43 + long result = redis.incr(key, 1L);
  44 + if (result > Integer.MAX_VALUE) {
  45 + redis.set(key, 1);
  46 + result = 1;
  47 + }
  48 + return result;
  49 + }
  50 +
  51 + @Override
  52 + public void resetAllCSEQ() {
  53 + String scanKey = VideoManagerConstants.SIP_CSEQ_PREFIX + userSetup.getServerId() + "_*";
  54 + List<Object> keys = redis.scan(scanKey);
  55 + for (int i = 0; i < keys.size(); i++) {
  56 + String key = (String) keys.get(i);
  57 + redis.set(key, 1);
  58 + }
  59 + }
  60 +
39 61 /**
40 62 * 开始播放时将流存入redis
41 63 *
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java
... ... @@ -9,7 +9,6 @@ import com.genersoft.iot.vmp.service.IMediaServerService;
9 9 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
10 10 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
11 11 import com.genersoft.iot.vmp.service.IPlayService;
12   -import com.genersoft.iot.vmp.vmanager.gb28181.session.InfoCseqCache;
13 12 import io.swagger.annotations.Api;
14 13 import io.swagger.annotations.ApiImplicitParam;
15 14 import io.swagger.annotations.ApiImplicitParams;
... ... @@ -31,7 +30,6 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
31 30 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
32 31 import org.springframework.web.context.request.async.DeferredResult;
33 32  
34   -import javax.sip.message.Response;
35 33 import java.util.UUID;
36 34  
37 35 @Api(tags = "视频回放")
... ... @@ -168,7 +166,6 @@ public class PlaybackController {
168 166 logger.warn("streamId不存在!");
169 167 return new ResponseEntity<String>(json.toString(), HttpStatus.BAD_REQUEST);
170 168 }
171   - setCseq(streamId);
172 169 Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
173 170 cmder.playPauseCmd(device, streamInfo);
174 171 json.put("msg", "ok");
... ... @@ -189,7 +186,6 @@ public class PlaybackController {
189 186 logger.warn("streamId不存在!");
190 187 return new ResponseEntity<String>(json.toString(), HttpStatus.BAD_REQUEST);
191 188 }
192   - setCseq(streamId);
193 189 Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
194 190 cmder.playResumeCmd(device, streamInfo);
195 191 json.put("msg", "ok");
... ... @@ -211,7 +207,6 @@ public class PlaybackController {
211 207 logger.warn("streamId不存在!");
212 208 return new ResponseEntity<String>(json.toString(), HttpStatus.BAD_REQUEST);
213 209 }
214   - setCseq(streamId);
215 210 Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
216 211 cmder.playSeekCmd(device, streamInfo, seekTime);
217 212 json.put("msg", "ok");
... ... @@ -238,18 +233,10 @@ public class PlaybackController {
238 233 logger.warn("不支持的speed: " + speed);
239 234 return new ResponseEntity<String>(json.toString(), HttpStatus.BAD_REQUEST);
240 235 }
241   - setCseq(streamId);
242 236 Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
243 237 cmder.playSpeedCmd(device, streamInfo, speed);
244 238 json.put("msg", "ok");
245 239 return new ResponseEntity<String>(json.toString(), HttpStatus.OK);
246 240 }
247 241  
248   - public void setCseq(String streamId) {
249   - if (InfoCseqCache.CSEQCACHE.containsKey(streamId)) {
250   - InfoCseqCache.CSEQCACHE.put(streamId, InfoCseqCache.CSEQCACHE.get(streamId) + 1);
251   - } else {
252   - InfoCseqCache.CSEQCACHE.put(streamId, 2L);
253   - }
254   - }
255 242 }
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/session/InfoCseqCache.java deleted 100644 → 0
1   -package com.genersoft.iot.vmp.vmanager.gb28181.session;
2   -
3   -import java.util.Map;
4   -import java.util.concurrent.ConcurrentHashMap;
5   -
6   -/**
7   - * @ClassName: InfoCseqCache
8   - * @Description: INFO类型的Sip中cseq的缓存
9   - */
10   -public class InfoCseqCache {
11   -
12   - public static Map<String, Long> CSEQCACHE = new ConcurrentHashMap<>();
13   -
14   -}
15 0 \ No newline at end of file