Commit 5749cdd16cd79890c659775de9b1cb7e7ffda5b1

Authored by 648540858
Committed by GitHub
2 parents 1ec70660 9b18c33d

Merge pull request #6 from lawrencehj/master

修正Message Resquest处理的错误等
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -329,7 +329,7 @@ public class SIPCommander implements ISIPCommander { @@ -329,7 +329,7 @@ public class SIPCommander implements ISIPCommander {
329 streamInfo.setSsrc(ssrc); 329 streamInfo.setSsrc(ssrc);
330 streamInfo.setCahnnelId(channelId); 330 streamInfo.setCahnnelId(channelId);
331 streamInfo.setDeviceID(device.getDeviceId()); 331 streamInfo.setDeviceID(device.getDeviceId());
332 - boolean b = storager.startPlayBlack(streamInfo); 332 + boolean b = storager.startPlayback(streamInfo);
333 return streamInfo; 333 return streamInfo;
334 334
335 } catch ( SipException | ParseException | InvalidArgumentException e) { 335 } catch ( SipException | ParseException | InvalidArgumentException e) {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
@@ -35,51 +35,51 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorager; @@ -35,51 +35,51 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
35 import com.genersoft.iot.vmp.utils.redis.RedisUtil; 35 import com.genersoft.iot.vmp.utils.redis.RedisUtil;
36 import org.springframework.util.StringUtils; 36 import org.springframework.util.StringUtils;
37 37
38 -/** 38 +/**
39 * @Description:MESSAGE请求处理器 39 * @Description:MESSAGE请求处理器
40 * @author: swwheihei 40 * @author: swwheihei
41 - * @date: 2020年5月3日 下午5:32:41 41 + * @date: 2020年5月3日 下午5:32:41
42 */ 42 */
43 public class MessageRequestProcessor extends SIPRequestAbstractProcessor { 43 public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
44 - 44 +
45 private final static Logger logger = LoggerFactory.getLogger(MessageRequestProcessor.class); 45 private final static Logger logger = LoggerFactory.getLogger(MessageRequestProcessor.class);
46 - 46 +
47 private SIPCommander cmder; 47 private SIPCommander cmder;
48 - 48 +
49 private IVideoManagerStorager storager; 49 private IVideoManagerStorager storager;
50 - 50 +
51 private EventPublisher publisher; 51 private EventPublisher publisher;
52 - 52 +
53 private RedisUtil redis; 53 private RedisUtil redis;
54 - 54 +
55 private DeferredResultHolder deferredResultHolder; 55 private DeferredResultHolder deferredResultHolder;
56 - 56 +
57 private DeviceOffLineDetector offLineDetector; 57 private DeviceOffLineDetector offLineDetector;
58 - 58 +
59 private final static String CACHE_RECORDINFO_KEY = "CACHE_RECORDINFO_"; 59 private final static String CACHE_RECORDINFO_KEY = "CACHE_RECORDINFO_";
60 - 60 +
61 private static final String MESSAGE_KEEP_ALIVE = "Keepalive"; 61 private static final String MESSAGE_KEEP_ALIVE = "Keepalive";
62 private static final String MESSAGE_CONFIG_DOWNLOAD = "ConfigDownload"; 62 private static final String MESSAGE_CONFIG_DOWNLOAD = "ConfigDownload";
63 private static final String MESSAGE_CATALOG = "Catalog"; 63 private static final String MESSAGE_CATALOG = "Catalog";
64 private static final String MESSAGE_DEVICE_INFO = "DeviceInfo"; 64 private static final String MESSAGE_DEVICE_INFO = "DeviceInfo";
65 private static final String MESSAGE_ALARM = "Alarm"; 65 private static final String MESSAGE_ALARM = "Alarm";
66 private static final String MESSAGE_RECORD_INFO = "RecordInfo"; 66 private static final String MESSAGE_RECORD_INFO = "RecordInfo";
67 -// private static final String MESSAGE_BROADCAST = "Broadcast";  
68 -// private static final String MESSAGE_DEVICE_STATUS = "DeviceStatus";  
69 -// private static final String MESSAGE_MOBILE_POSITION = "MobilePosition";  
70 -// private static final String MESSAGE_MOBILE_POSITION_INTERVAL = "Interval";  
71 -  
72 - /** 67 + // private static final String MESSAGE_BROADCAST = "Broadcast";
  68 + // private static final String MESSAGE_DEVICE_STATUS = "DeviceStatus";
  69 + // private static final String MESSAGE_MOBILE_POSITION = "MobilePosition";
  70 + // private static final String MESSAGE_MOBILE_POSITION_INTERVAL = "Interval";
  71 +
  72 + /**
73 * 处理MESSAGE请求 73 * 处理MESSAGE请求
74 - * 74 + *
75 * @param evt 75 * @param evt
76 - */ 76 + */
77 @Override 77 @Override
78 public void process(RequestEvent evt) { 78 public void process(RequestEvent evt) {
79 79
80 try { 80 try {
81 Element rootElement = getRootElement(evt); 81 Element rootElement = getRootElement(evt);
82 - String cmd = XmlUtil.getText(rootElement,"CmdType"); 82 + String cmd = XmlUtil.getText(rootElement, "CmdType");
83 83
84 if (MESSAGE_KEEP_ALIVE.equals(cmd)) { 84 if (MESSAGE_KEEP_ALIVE.equals(cmd)) {
85 logger.info("接收到KeepAlive消息"); 85 logger.info("接收到KeepAlive消息");
@@ -103,9 +103,10 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { @@ -103,9 +103,10 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
103 e.printStackTrace(); 103 e.printStackTrace();
104 } 104 }
105 } 105 }
106 - 106 +
107 /** 107 /**
108 * 收到deviceInfo设备信息请求 处理 108 * 收到deviceInfo设备信息请求 处理
  109 + *
109 * @param evt 110 * @param evt
110 */ 111 */
111 private void processMessageDeviceInfo(RequestEvent evt) { 112 private void processMessageDeviceInfo(RequestEvent evt) {
@@ -113,32 +114,38 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { @@ -113,32 +114,38 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
113 Element rootElement = getRootElement(evt); 114 Element rootElement = getRootElement(evt);
114 Element deviceIdElement = rootElement.element("DeviceID"); 115 Element deviceIdElement = rootElement.element("DeviceID");
115 String deviceId = deviceIdElement.getText().toString(); 116 String deviceId = deviceIdElement.getText().toString();
116 - 117 +
117 Device device = storager.queryVideoDevice(deviceId); 118 Device device = storager.queryVideoDevice(deviceId);
118 if (device == null) { 119 if (device == null) {
119 return; 120 return;
120 } 121 }
121 - device.setName(XmlUtil.getText(rootElement,"DeviceName"));  
122 - device.setManufacturer(XmlUtil.getText(rootElement,"Manufacturer"));  
123 - device.setModel(XmlUtil.getText(rootElement,"Model"));  
124 - device.setFirmware(XmlUtil.getText(rootElement,"Firmware"));  
125 - if (StringUtils.isEmpty(device.getStreamMode())){ 122 + device.setName(XmlUtil.getText(rootElement, "DeviceName"));
  123 + device.setManufacturer(XmlUtil.getText(rootElement, "Manufacturer"));
  124 + device.setModel(XmlUtil.getText(rootElement, "Model"));
  125 + device.setFirmware(XmlUtil.getText(rootElement, "Firmware"));
  126 + if (StringUtils.isEmpty(device.getStreamMode())) {
126 device.setStreamMode("UDP"); 127 device.setStreamMode("UDP");
127 } 128 }
128 storager.updateDevice(device); 129 storager.updateDevice(device);
129 - 130 +
130 RequestMessage msg = new RequestMessage(); 131 RequestMessage msg = new RequestMessage();
131 msg.setDeviceId(deviceId); 132 msg.setDeviceId(deviceId);
132 msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICEINFO); 133 msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICEINFO);
133 msg.setData(device); 134 msg.setData(device);
134 deferredResultHolder.invokeResult(msg); 135 deferredResultHolder.invokeResult(msg);
135 - } catch (DocumentException e) { 136 + // 回复200 OK
  137 + responseAck(evt);
  138 + if (offLineDetector.isOnline(deviceId)) {
  139 + publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
  140 + }
  141 + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
136 e.printStackTrace(); 142 e.printStackTrace();
137 } 143 }
138 } 144 }
139 - 145 +
140 /*** 146 /***
141 * 收到catalog设备目录列表请求 处理 147 * 收到catalog设备目录列表请求 处理
  148 + *
142 * @param evt 149 * @param evt
143 */ 150 */
144 private void processMessageCatalogList(RequestEvent evt) { 151 private void processMessageCatalogList(RequestEvent evt) {
@@ -171,34 +178,43 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { @@ -171,34 +178,43 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
171 DeviceChannel deviceChannel = new DeviceChannel(); 178 DeviceChannel deviceChannel = new DeviceChannel();
172 deviceChannel.setName(channelName); 179 deviceChannel.setName(channelName);
173 deviceChannel.setChannelId(channelDeviceId); 180 deviceChannel.setChannelId(channelDeviceId);
174 - if(status.equals("ON") || status.equals("On")) { 181 + if (status.equals("ON") || status.equals("On")) {
175 deviceChannel.setStatus(1); 182 deviceChannel.setStatus(1);
176 } 183 }
177 - if(status.equals("OFF") || status.equals("Off")) { 184 + if (status.equals("OFF") || status.equals("Off")) {
178 deviceChannel.setStatus(0); 185 deviceChannel.setStatus(0);
179 } 186 }
180 187
181 - deviceChannel.setManufacture(XmlUtil.getText(itemDevice,"Manufacturer"));  
182 - deviceChannel.setModel(XmlUtil.getText(itemDevice,"Model"));  
183 - deviceChannel.setOwner(XmlUtil.getText(itemDevice,"Owner"));  
184 - deviceChannel.setCivilCode(XmlUtil.getText(itemDevice,"CivilCode"));  
185 - deviceChannel.setBlock(XmlUtil.getText(itemDevice,"Block"));  
186 - deviceChannel.setAddress(XmlUtil.getText(itemDevice,"Address"));  
187 - deviceChannel.setParental(itemDevice.element("Parental") == null? 0:Integer.parseInt(XmlUtil.getText(itemDevice,"Parental")));  
188 - deviceChannel.setParentId(XmlUtil.getText(itemDevice,"ParentID"));  
189 - deviceChannel.setSafetyWay(itemDevice.element("SafetyWay") == null? 0:Integer.parseInt(XmlUtil.getText(itemDevice,"SafetyWay")));  
190 - deviceChannel.setRegisterWay(itemDevice.element("RegisterWay") == null? 1:Integer.parseInt(XmlUtil.getText(itemDevice,"RegisterWay")));  
191 - deviceChannel.setCertNum(XmlUtil.getText(itemDevice,"CertNum"));  
192 - deviceChannel.setCertifiable(itemDevice.element("Certifiable") == null? 0:Integer.parseInt(XmlUtil.getText(itemDevice,"Certifiable")));  
193 - deviceChannel.setErrCode(itemDevice.element("ErrCode") == null? 0:Integer.parseInt(XmlUtil.getText(itemDevice,"ErrCode")));  
194 - deviceChannel.setEndTime(XmlUtil.getText(itemDevice,"EndTime"));  
195 - deviceChannel.setSecrecy(XmlUtil.getText(itemDevice,"Secrecy"));  
196 - deviceChannel.setIpAddress(XmlUtil.getText(itemDevice,"IPAddress"));  
197 - deviceChannel.setPort(itemDevice.element("Port") == null? 0:Integer.parseInt(XmlUtil.getText(itemDevice,"Port")));  
198 - deviceChannel.setPassword(XmlUtil.getText(itemDevice,"Password"));  
199 - deviceChannel.setLongitude(itemDevice.element("Longitude") == null? 0.00:Double.parseDouble(XmlUtil.getText(itemDevice,"Longitude")));  
200 - deviceChannel.setLatitude(itemDevice.element("Latitude") == null? 0.00:Double.parseDouble(XmlUtil.getText(itemDevice,"Latitude")));  
201 - deviceChannel.setPTZType(itemDevice.element("PTZType") == null? 0:Integer.parseInt(XmlUtil.getText(itemDevice,"PTZType"))); 188 + deviceChannel.setManufacture(XmlUtil.getText(itemDevice, "Manufacturer"));
  189 + deviceChannel.setModel(XmlUtil.getText(itemDevice, "Model"));
  190 + deviceChannel.setOwner(XmlUtil.getText(itemDevice, "Owner"));
  191 + deviceChannel.setCivilCode(XmlUtil.getText(itemDevice, "CivilCode"));
  192 + deviceChannel.setBlock(XmlUtil.getText(itemDevice, "Block"));
  193 + deviceChannel.setAddress(XmlUtil.getText(itemDevice, "Address"));
  194 + deviceChannel.setParental(itemDevice.element("Parental") == null ? 0
  195 + : Integer.parseInt(XmlUtil.getText(itemDevice, "Parental")));
  196 + deviceChannel.setParentId(XmlUtil.getText(itemDevice, "ParentID"));
  197 + deviceChannel.setSafetyWay(itemDevice.element("SafetyWay") == null ? 0
  198 + : Integer.parseInt(XmlUtil.getText(itemDevice, "SafetyWay")));
  199 + deviceChannel.setRegisterWay(itemDevice.element("RegisterWay") == null ? 1
  200 + : Integer.parseInt(XmlUtil.getText(itemDevice, "RegisterWay")));
  201 + deviceChannel.setCertNum(XmlUtil.getText(itemDevice, "CertNum"));
  202 + deviceChannel.setCertifiable(itemDevice.element("Certifiable") == null ? 0
  203 + : Integer.parseInt(XmlUtil.getText(itemDevice, "Certifiable")));
  204 + deviceChannel.setErrCode(itemDevice.element("ErrCode") == null ? 0
  205 + : Integer.parseInt(XmlUtil.getText(itemDevice, "ErrCode")));
  206 + deviceChannel.setEndTime(XmlUtil.getText(itemDevice, "EndTime"));
  207 + deviceChannel.setSecrecy(XmlUtil.getText(itemDevice, "Secrecy"));
  208 + deviceChannel.setIpAddress(XmlUtil.getText(itemDevice, "IPAddress"));
  209 + deviceChannel.setPort(itemDevice.element("Port") == null ? 0
  210 + : Integer.parseInt(XmlUtil.getText(itemDevice, "Port")));
  211 + deviceChannel.setPassword(XmlUtil.getText(itemDevice, "Password"));
  212 + deviceChannel.setLongitude(itemDevice.element("Longitude") == null ? 0.00
  213 + : Double.parseDouble(XmlUtil.getText(itemDevice, "Longitude")));
  214 + deviceChannel.setLatitude(itemDevice.element("Latitude") == null ? 0.00
  215 + : Double.parseDouble(XmlUtil.getText(itemDevice, "Latitude")));
  216 + deviceChannel.setPTZType(itemDevice.element("PTZType") == null ? 0
  217 + : Integer.parseInt(XmlUtil.getText(itemDevice, "PTZType")));
202 deviceChannel.setHasAudio(true); // 默认含有音频,播放时再检查是否有音频及是否AAC 218 deviceChannel.setHasAudio(true); // 默认含有音频,播放时再检查是否有音频及是否AAC
203 storager.updateChannel(device.getDeviceId(), deviceChannel); 219 storager.updateChannel(device.getDeviceId(), deviceChannel);
204 } 220 }
@@ -208,21 +224,20 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { @@ -208,21 +224,20 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
208 msg.setType(DeferredResultHolder.CALLBACK_CMD_CATALOG); 224 msg.setType(DeferredResultHolder.CALLBACK_CMD_CATALOG);
209 msg.setData(device); 225 msg.setData(device);
210 deferredResultHolder.invokeResult(msg); 226 deferredResultHolder.invokeResult(msg);
211 -  
212 - // 回复200 227 + // 回复200 OK
  228 + responseAck(evt);
213 if (offLineDetector.isOnline(deviceId)) { 229 if (offLineDetector.isOnline(deviceId)) {
214 - responseAck(evt);  
215 publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); 230 publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
216 } 231 }
217 -  
218 } 232 }
219 } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { 233 } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
220 e.printStackTrace(); 234 e.printStackTrace();
221 } 235 }
222 } 236 }
223 - 237 +
224 /*** 238 /***
225 * 收到alarm设备报警信息 处理 239 * 收到alarm设备报警信息 处理
  240 + *
226 * @param evt 241 * @param evt
227 */ 242 */
228 private void processMessageAlarm(RequestEvent evt) { 243 private void processMessageAlarm(RequestEvent evt) {
@@ -230,37 +245,45 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { @@ -230,37 +245,45 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
230 Element rootElement = getRootElement(evt); 245 Element rootElement = getRootElement(evt);
231 Element deviceIdElement = rootElement.element("DeviceID"); 246 Element deviceIdElement = rootElement.element("DeviceID");
232 String deviceId = deviceIdElement.getText().toString(); 247 String deviceId = deviceIdElement.getText().toString();
233 - 248 +
234 Device device = storager.queryVideoDevice(deviceId); 249 Device device = storager.queryVideoDevice(deviceId);
235 if (device == null) { 250 if (device == null) {
236 // TODO 也可能是通道 251 // TODO 也可能是通道
237 -// storager.queryChannel(deviceId) 252 + // storager.queryChannel(deviceId)
238 return; 253 return;
239 } 254 }
240 - device.setName(XmlUtil.getText(rootElement,"DeviceName"));  
241 - device.setManufacturer(XmlUtil.getText(rootElement,"Manufacturer"));  
242 - device.setModel(XmlUtil.getText(rootElement,"Model"));  
243 - device.setFirmware(XmlUtil.getText(rootElement,"Firmware"));  
244 - if (StringUtils.isEmpty(device.getStreamMode())){ 255 + device.setName(XmlUtil.getText(rootElement, "DeviceName"));
  256 + device.setManufacturer(XmlUtil.getText(rootElement, "Manufacturer"));
  257 + device.setModel(XmlUtil.getText(rootElement, "Model"));
  258 + device.setFirmware(XmlUtil.getText(rootElement, "Firmware"));
  259 + if (StringUtils.isEmpty(device.getStreamMode())) {
245 device.setStreamMode("UDP"); 260 device.setStreamMode("UDP");
246 } 261 }
247 storager.updateDevice(device); 262 storager.updateDevice(device);
248 cmder.catalogQuery(device); 263 cmder.catalogQuery(device);
249 - } catch (DocumentException e) { 264 + // 回复200 OK
  265 + responseAck(evt);
  266 + if (offLineDetector.isOnline(deviceId)) {
  267 + publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
  268 + }
  269 + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
  270 + // } catch (DocumentException e) {
250 e.printStackTrace(); 271 e.printStackTrace();
251 } 272 }
252 } 273 }
253 - 274 +
254 /*** 275 /***
255 * 收到keepalive请求 处理 276 * 收到keepalive请求 处理
  277 + *
256 * @param evt 278 * @param evt
257 */ 279 */
258 - private void processMessageKeepAlive(RequestEvent evt){ 280 + private void processMessageKeepAlive(RequestEvent evt) {
259 try { 281 try {
260 Element rootElement = getRootElement(evt); 282 Element rootElement = getRootElement(evt);
261 - String deviceId = XmlUtil.getText(rootElement,"DeviceID"); 283 + String deviceId = XmlUtil.getText(rootElement, "DeviceID");
  284 + // 回复200 OK
  285 + responseAck(evt);
262 if (offLineDetector.isOnline(deviceId)) { 286 if (offLineDetector.isOnline(deviceId)) {
263 - responseAck(evt);  
264 publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); 287 publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
265 } else { 288 } else {
266 } 289 }
@@ -268,58 +291,66 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { @@ -268,58 +291,66 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
268 e.printStackTrace(); 291 e.printStackTrace();
269 } 292 }
270 } 293 }
271 - 294 +
272 /*** 295 /***
273 - * 收到catalog设备目录列表请求 处理  
274 - * TODO 过期时间暂时写死180秒,后续与DeferredResult超时时间保持一致 296 + * 收到catalog设备目录列表请求 处理 TODO 过期时间暂时写死180秒,后续与DeferredResult超时时间保持一致
  297 + *
275 * @param evt 298 * @param evt
276 */ 299 */
277 private void processMessageRecordInfo(RequestEvent evt) { 300 private void processMessageRecordInfo(RequestEvent evt) {
278 try { 301 try {
  302 + // 回复200 OK
  303 + responseAck(evt);
279 RecordInfo recordInfo = new RecordInfo(); 304 RecordInfo recordInfo = new RecordInfo();
280 Element rootElement = getRootElement(evt); 305 Element rootElement = getRootElement(evt);
281 Element deviceIdElement = rootElement.element("DeviceID"); 306 Element deviceIdElement = rootElement.element("DeviceID");
282 String deviceId = deviceIdElement.getText().toString(); 307 String deviceId = deviceIdElement.getText().toString();
283 recordInfo.setDeviceId(deviceId); 308 recordInfo.setDeviceId(deviceId);
284 - recordInfo.setName(XmlUtil.getText(rootElement,"Name"));  
285 - recordInfo.setSumNum(Integer.parseInt(XmlUtil.getText(rootElement,"SumNum")));  
286 - String sn = XmlUtil.getText(rootElement,"SN"); 309 + recordInfo.setName(XmlUtil.getText(rootElement, "Name"));
  310 + recordInfo.setSumNum(Integer.parseInt(XmlUtil.getText(rootElement, "SumNum")));
  311 + String sn = XmlUtil.getText(rootElement, "SN");
287 Element recordListElement = rootElement.element("RecordList"); 312 Element recordListElement = rootElement.element("RecordList");
288 if (recordListElement == null) { 313 if (recordListElement == null) {
  314 + logger.info("无录像数据");
  315 + // responseAck(evt);
289 return; 316 return;
290 } 317 }
291 - 318 +
292 Iterator<Element> recordListIterator = recordListElement.elementIterator(); 319 Iterator<Element> recordListIterator = recordListElement.elementIterator();
293 List<RecordItem> recordList = new ArrayList<RecordItem>(); 320 List<RecordItem> recordList = new ArrayList<RecordItem>();
294 if (recordListIterator != null) { 321 if (recordListIterator != null) {
295 RecordItem record = new RecordItem(); 322 RecordItem record = new RecordItem();
  323 + logger.info("处理录像列表数据...");
296 // 遍历DeviceList 324 // 遍历DeviceList
297 while (recordListIterator.hasNext()) { 325 while (recordListIterator.hasNext()) {
298 Element itemRecord = recordListIterator.next(); 326 Element itemRecord = recordListIterator.next();
299 Element recordElement = itemRecord.element("DeviceID"); 327 Element recordElement = itemRecord.element("DeviceID");
300 if (recordElement == null) { 328 if (recordElement == null) {
  329 + logger.info("记录为空,下一个...");
301 continue; 330 continue;
302 } 331 }
303 record = new RecordItem(); 332 record = new RecordItem();
304 - record.setDeviceId(XmlUtil.getText(itemRecord,"DeviceID"));  
305 - record.setName(XmlUtil.getText(itemRecord,"Name"));  
306 - record.setFilePath(XmlUtil.getText(itemRecord,"FilePath"));  
307 - record.setAddress(XmlUtil.getText(itemRecord,"Address"));  
308 - record.setStartTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(XmlUtil.getText(itemRecord,"StartTime")));  
309 - record.setEndTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(XmlUtil.getText(itemRecord,"EndTime")));  
310 - record.setSecrecy(itemRecord.element("Secrecy") == null? 0:Integer.parseInt(XmlUtil.getText(itemRecord,"Secrecy")));  
311 - record.setType(XmlUtil.getText(itemRecord,"Type"));  
312 - record.setRecorderId(XmlUtil.getText(itemRecord,"RecorderID")); 333 + record.setDeviceId(XmlUtil.getText(itemRecord, "DeviceID"));
  334 + record.setName(XmlUtil.getText(itemRecord, "Name"));
  335 + record.setFilePath(XmlUtil.getText(itemRecord, "FilePath"));
  336 + record.setAddress(XmlUtil.getText(itemRecord, "Address"));
  337 + record.setStartTime(
  338 + DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(XmlUtil.getText(itemRecord, "StartTime")));
  339 + record.setEndTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(XmlUtil.getText(itemRecord, "EndTime")));
  340 + record.setSecrecy(itemRecord.element("Secrecy") == null ? 0
  341 + : Integer.parseInt(XmlUtil.getText(itemRecord, "Secrecy")));
  342 + record.setType(XmlUtil.getText(itemRecord, "Type"));
  343 + record.setRecorderId(XmlUtil.getText(itemRecord, "RecorderID"));
313 recordList.add(record); 344 recordList.add(record);
314 } 345 }
315 -// recordList.sort(Comparator.naturalOrder()); 346 + // recordList.sort(Comparator.naturalOrder());
316 recordInfo.setRecordList(recordList); 347 recordInfo.setRecordList(recordList);
317 } 348 }
318 - 349 +
319 // 存在录像且如果当前录像明细个数小于总条数,说明拆包返回,需要组装,暂不返回 350 // 存在录像且如果当前录像明细个数小于总条数,说明拆包返回,需要组装,暂不返回
320 if (recordInfo.getSumNum() > 0 && recordList.size() > 0 && recordList.size() < recordInfo.getSumNum()) { 351 if (recordInfo.getSumNum() > 0 && recordList.size() > 0 && recordList.size() < recordInfo.getSumNum()) {
321 // 为防止连续请求该设备的录像数据,返回数据错乱,特增加sn进行区分 352 // 为防止连续请求该设备的录像数据,返回数据错乱,特增加sn进行区分
322 - String cacheKey = CACHE_RECORDINFO_KEY+deviceId+sn; 353 + String cacheKey = CACHE_RECORDINFO_KEY + deviceId + sn;
323 // TODO 暂时直接操作redis存储,后续封装专用缓存接口,改为本地内存缓存 354 // TODO 暂时直接操作redis存储,后续封装专用缓存接口,改为本地内存缓存
324 if (redis.hasKey(cacheKey)) { 355 if (redis.hasKey(cacheKey)) {
325 List<RecordItem> previousList = (List<RecordItem>) redis.get(cacheKey); 356 List<RecordItem> previousList = (List<RecordItem>) redis.get(cacheKey);
@@ -328,24 +359,28 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { @@ -328,24 +359,28 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
328 } 359 }
329 // 本分支表示录像列表被拆包,且加上之前的数据还是不够,保存缓存返回,等待下个包再处理 360 // 本分支表示录像列表被拆包,且加上之前的数据还是不够,保存缓存返回,等待下个包再处理
330 if (recordList.size() < recordInfo.getSumNum()) { 361 if (recordList.size() < recordInfo.getSumNum()) {
331 - redis.set(cacheKey, recordList, 180); 362 + logger.info("已获取" + recordList.size() + "项录像数据,共" + recordInfo.getSumNum() + "项");
  363 + redis.set(cacheKey, recordList, 90);
332 return; 364 return;
333 } else { 365 } else {
334 // 本分支表示录像被拆包,但加上之前的数据够足够,返回响应 366 // 本分支表示录像被拆包,但加上之前的数据够足够,返回响应
335 // 因设备心跳有监听redis过期机制,为提高性能,此处手动删除 367 // 因设备心跳有监听redis过期机制,为提高性能,此处手动删除
  368 + logger.info("录像数据已全部获取");
336 redis.del(cacheKey); 369 redis.del(cacheKey);
337 } 370 }
338 } else { 371 } else {
339 // 本分支有两种可能:1、录像列表被拆包,且是第一个包,直接保存缓存返回,等待下个包再处理 372 // 本分支有两种可能:1、录像列表被拆包,且是第一个包,直接保存缓存返回,等待下个包再处理
340 - // 2、之前有包,但超时清空了,那么这次sn批次的响应数据已经不完整,等待过期时间后redis自动清空数据  
341 - redis.set(cacheKey, recordList, 180); 373 + // 2、之前有包,但超时清空了,那么这次sn批次的响应数据已经不完整,等待过期时间后redis自动清空数据
  374 + logger.info("等待后续的包...");
  375 +
  376 + redis.set(cacheKey, recordList, 90);
342 return; 377 return;
343 } 378 }
344 - 379 +
345 } 380 }
346 // 走到这里,有以下可能:1、没有录像信息,第一次收到recordinfo的消息即返回响应数据,无redis操作 381 // 走到这里,有以下可能:1、没有录像信息,第一次收到recordinfo的消息即返回响应数据,无redis操作
347 - // 2、有录像数据,且第一次即收到完整数据,返回响应数据,无redis操作  
348 - // 3、有录像数据,在超时时间内收到多次包组装后数量足够,返回数据 382 + // 2、有录像数据,且第一次即收到完整数据,返回响应数据,无redis操作
  383 + // 3、有录像数据,在超时时间内收到多次包组装后数量足够,返回数据
349 384
350 // 对记录进行排序 385 // 对记录进行排序
351 RequestMessage msg = new RequestMessage(); 386 RequestMessage msg = new RequestMessage();
@@ -355,16 +390,17 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { @@ -355,16 +390,17 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
355 recordInfo.getRecordList().sort(Comparator.naturalOrder()); 390 recordInfo.getRecordList().sort(Comparator.naturalOrder());
356 msg.setData(recordInfo); 391 msg.setData(recordInfo);
357 deferredResultHolder.invokeResult(msg); 392 deferredResultHolder.invokeResult(msg);
358 - } catch (DocumentException e) { 393 + logger.info("处理完成,返回结果");
  394 + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
359 e.printStackTrace(); 395 e.printStackTrace();
360 } 396 }
361 } 397 }
362 - 398 +
363 private void responseAck(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException { 399 private void responseAck(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException {
364 - Response response = getMessageFactory().createResponse(Response.OK,evt.getRequest()); 400 + Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
365 getServerTransaction(evt).sendResponse(response); 401 getServerTransaction(evt).sendResponse(response);
366 } 402 }
367 - 403 +
368 private Element getRootElement(RequestEvent evt) throws DocumentException { 404 private Element getRootElement(RequestEvent evt) throws DocumentException {
369 Request request = evt.getRequest(); 405 Request request = evt.getRequest();
370 SAXReader reader = new SAXReader(); 406 SAXReader reader = new SAXReader();
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -142,7 +142,7 @@ public class ZLMHttpHookListener { @@ -142,7 +142,7 @@ public class ZLMHttpHookListener {
142 storager.startPlay(streamInfoForPlay); 142 storager.startPlay(streamInfoForPlay);
143 } 143 }
144 144
145 - StreamInfo streamInfoForPlayBack = storager.queryPlayBlackBySSRC(ssrc); 145 + StreamInfo streamInfoForPlayBack = storager.queryPlaybackBySSRC(ssrc);
146 if ("rtp".equals(app) && streamInfoForPlayBack != null ) { 146 if ("rtp".equals(app) && streamInfoForPlayBack != null ) {
147 MediaServerConfig mediaInfo = storager.getMediaInfo(); 147 MediaServerConfig mediaInfo = storager.getMediaInfo();
148 streamInfoForPlayBack.setFlv(String.format("http://%s:%s/rtp/%s.flv", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId)); 148 streamInfoForPlayBack.setFlv(String.format("http://%s:%s/rtp/%s.flv", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId));
@@ -150,7 +150,7 @@ public class ZLMHttpHookListener { @@ -150,7 +150,7 @@ public class ZLMHttpHookListener {
150 streamInfoForPlayBack.setRtmp(String.format("rtmp://%s:%s/rtp/%s", mediaInfo.getLocalIP(), mediaInfo.getRtmpPort(), streamId)); 150 streamInfoForPlayBack.setRtmp(String.format("rtmp://%s:%s/rtp/%s", mediaInfo.getLocalIP(), mediaInfo.getRtmpPort(), streamId));
151 streamInfoForPlayBack.setHls(String.format("http://%s:%s/rtp/%s/hls.m3u8", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId)); 151 streamInfoForPlayBack.setHls(String.format("http://%s:%s/rtp/%s/hls.m3u8", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId));
152 streamInfoForPlayBack.setRtsp(String.format("rtsp://%s:%s/rtp/%s", mediaInfo.getLocalIP(), mediaInfo.getRtspPort(), streamId)); 152 streamInfoForPlayBack.setRtsp(String.format("rtsp://%s:%s/rtp/%s", mediaInfo.getLocalIP(), mediaInfo.getRtspPort(), streamId));
153 - storager.startPlayBlack(streamInfoForPlayBack); 153 + storager.startPlayback(streamInfoForPlayBack);
154 } 154 }
155 155
156 // TODO Auto-generated method stub 156 // TODO Auto-generated method stub
@@ -261,7 +261,12 @@ public class ZLMHttpHookListener { @@ -261,7 +261,12 @@ public class ZLMHttpHookListener {
261 String ssrc = new DecimalFormat("0000000000").format(Integer.parseInt(streamId, 16)); 261 String ssrc = new DecimalFormat("0000000000").format(Integer.parseInt(streamId, 16));
262 StreamInfo streamInfo = storager.queryPlayBySSRC(ssrc); 262 StreamInfo streamInfo = storager.queryPlayBySSRC(ssrc);
263 if ("rtp".equals(app) && !regist ) { 263 if ("rtp".equals(app) && !regist ) {
264 - storager.stopPlay(streamInfo); 264 + if (streamInfo!=null){
  265 + storager.stopPlay(streamInfo);
  266 + }else{
  267 + streamInfo = storager.queryPlaybackBySSRC(ssrc);
  268 + storager.stopPlayback(streamInfo);
  269 + }
265 } 270 }
266 271
267 272
@@ -288,6 +293,13 @@ public class ZLMHttpHookListener { @@ -288,6 +293,13 @@ public class ZLMHttpHookListener {
288 String ssrc = String.format("%010d", numb); 293 String ssrc = String.format("%010d", numb);
289 294
290 cmder.streamByeCmd(ssrc); 295 cmder.streamByeCmd(ssrc);
  296 + StreamInfo streamInfo = storager.queryPlayBySSRC(ssrc);
  297 + if (streamInfo!=null){
  298 + storager.stopPlay(streamInfo);
  299 + }else{
  300 + streamInfo = storager.queryPlaybackBySSRC(ssrc);
  301 + storager.stopPlayback(streamInfo);
  302 + }
291 303
292 JSONObject ret = new JSONObject(); 304 JSONObject ret = new JSONObject();
293 ret.put("code", 0); 305 ret.put("code", 0);
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java
@@ -184,11 +184,11 @@ public interface IVideoManagerStorager { @@ -184,11 +184,11 @@ public interface IVideoManagerStorager {
184 184
185 Map<String, StreamInfo> queryPlayByDeviceId(String deviceId); 185 Map<String, StreamInfo> queryPlayByDeviceId(String deviceId);
186 186
187 - boolean startPlayBlack(StreamInfo streamInfo); 187 + boolean startPlayback(StreamInfo streamInfo);
188 188
189 - boolean stopPlayBlack(StreamInfo streamInfo); 189 + boolean stopPlayback(StreamInfo streamInfo);
190 190
191 - StreamInfo queryPlayBlackByDevice(String deviceId, String channelId); 191 + StreamInfo queryPlaybackByDevice(String deviceId, String channelId);
192 192
193 - StreamInfo queryPlayBlackBySSRC(String ssrc); 193 + StreamInfo queryPlaybackBySSRC(String ssrc);
194 } 194 }
src/main/java/com/genersoft/iot/vmp/storager/jdbc/VideoManagerJdbcStoragerImpl.java
@@ -195,22 +195,22 @@ public class VideoManagerJdbcStoragerImpl implements IVideoManagerStorager { @@ -195,22 +195,22 @@ public class VideoManagerJdbcStoragerImpl implements IVideoManagerStorager {
195 } 195 }
196 196
197 @Override 197 @Override
198 - public boolean startPlayBlack(StreamInfo streamInfo) { 198 + public boolean startPlayback(StreamInfo streamInfo) {
199 return false; 199 return false;
200 } 200 }
201 201
202 @Override 202 @Override
203 - public boolean stopPlayBlack(StreamInfo streamInfo) { 203 + public boolean stopPlayback(StreamInfo streamInfo) {
204 return false; 204 return false;
205 } 205 }
206 206
207 @Override 207 @Override
208 - public StreamInfo queryPlayBlackByDevice(String deviceId, String channelId) { 208 + public StreamInfo queryPlaybackByDevice(String deviceId, String channelId) {
209 return null; 209 return null;
210 } 210 }
211 211
212 @Override 212 @Override
213 - public StreamInfo queryPlayBlackBySSRC(String ssrc) { 213 + public StreamInfo queryPlaybackBySSRC(String ssrc) {
214 return null; 214 return null;
215 } 215 }
216 } 216 }
src/main/java/com/genersoft/iot/vmp/storager/redis/VideoManagerRedisStoragerImpl.java
@@ -409,7 +409,7 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager { @@ -409,7 +409,7 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager {
409 } 409 }
410 410
411 @Override 411 @Override
412 - public StreamInfo queryPlayBlackBySSRC(String ssrc) { 412 + public StreamInfo queryPlaybackBySSRC(String ssrc) {
413 // List<Object> playLeys = redis.keys(String.format("%S_%s_*", VideoManagerConstants.PLAYER_PREFIX, ssrc)); 413 // List<Object> playLeys = redis.keys(String.format("%S_%s_*", VideoManagerConstants.PLAYER_PREFIX, ssrc));
414 List<Object> playLeys = redis.scan(String.format("%S_%s_*", VideoManagerConstants.PLAY_BLACK_PREFIX, ssrc)); 414 List<Object> playLeys = redis.scan(String.format("%S_%s_*", VideoManagerConstants.PLAY_BLACK_PREFIX, ssrc));
415 if (playLeys == null || playLeys.size() == 0) return null; 415 if (playLeys == null || playLeys.size() == 0) return null;
@@ -505,14 +505,14 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager { @@ -505,14 +505,14 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager {
505 505
506 506
507 @Override 507 @Override
508 - public boolean startPlayBlack(StreamInfo stream) { 508 + public boolean startPlayback(StreamInfo stream) {
509 return redis.set(String.format("%S_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, stream.getSsrc(),stream.getDeviceID(), stream.getCahnnelId()), 509 return redis.set(String.format("%S_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, stream.getSsrc(),stream.getDeviceID(), stream.getCahnnelId()),
510 stream); 510 stream);
511 } 511 }
512 512
513 513
514 @Override 514 @Override
515 - public boolean stopPlayBlack(StreamInfo streamInfo) { 515 + public boolean stopPlayback(StreamInfo streamInfo) {
516 if (streamInfo == null) return false; 516 if (streamInfo == null) return false;
517 DeviceChannel deviceChannel = queryChannel(streamInfo.getDeviceID(), streamInfo.getCahnnelId()); 517 DeviceChannel deviceChannel = queryChannel(streamInfo.getDeviceID(), streamInfo.getCahnnelId());
518 if (deviceChannel != null) { 518 if (deviceChannel != null) {
@@ -527,7 +527,7 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager { @@ -527,7 +527,7 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager {
527 } 527 }
528 528
529 @Override 529 @Override
530 - public StreamInfo queryPlayBlackByDevice(String deviceId, String code) { 530 + public StreamInfo queryPlaybackByDevice(String deviceId, String code) {
531 String format = String.format("%S_*_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, 531 String format = String.format("%S_*_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
532 deviceId, 532 deviceId,
533 code); 533 code);
src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java
@@ -26,32 +26,32 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorager; @@ -26,32 +26,32 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
26 @RestController 26 @RestController
27 @RequestMapping("/api") 27 @RequestMapping("/api")
28 public class PlayController { 28 public class PlayController {
29 - 29 +
30 private final static Logger logger = LoggerFactory.getLogger(PlayController.class); 30 private final static Logger logger = LoggerFactory.getLogger(PlayController.class);
31 - 31 +
32 @Autowired 32 @Autowired
33 private SIPCommander cmder; 33 private SIPCommander cmder;
34 - 34 +
35 @Autowired 35 @Autowired
36 private IVideoManagerStorager storager; 36 private IVideoManagerStorager storager;
37 37
38 @Autowired 38 @Autowired
39 private ZLMRESTfulUtils zlmresTfulUtils; 39 private ZLMRESTfulUtils zlmresTfulUtils;
40 - 40 +
41 @GetMapping("/play/{deviceId}/{channelId}") 41 @GetMapping("/play/{deviceId}/{channelId}")
42 - public ResponseEntity<String> play(@PathVariable String deviceId,@PathVariable String channelId){  
43 - 42 + public ResponseEntity<String> play(@PathVariable String deviceId, @PathVariable String channelId) {
  43 +
44 Device device = storager.queryVideoDevice(deviceId); 44 Device device = storager.queryVideoDevice(deviceId);
45 StreamInfo streamInfo = storager.queryPlayByDevice(deviceId, channelId); 45 StreamInfo streamInfo = storager.queryPlayByDevice(deviceId, channelId);
46 46
47 if (streamInfo == null) { 47 if (streamInfo == null) {
48 streamInfo = cmder.playStreamCmd(device, channelId); 48 streamInfo = cmder.playStreamCmd(device, channelId);
49 - }else { 49 + } else {
50 String streamId = String.format("%08x", Integer.parseInt(streamInfo.getSsrc())).toUpperCase(); 50 String streamId = String.format("%08x", Integer.parseInt(streamInfo.getSsrc())).toUpperCase();
51 JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId); 51 JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId);
52 if (rtpInfo.getBoolean("exist")) { 52 if (rtpInfo.getBoolean("exist")) {
53 - return new ResponseEntity<String>(JSON.toJSONString(streamInfo),HttpStatus.OK);  
54 - }else { 53 + return new ResponseEntity<String>(JSON.toJSONString(streamInfo), HttpStatus.OK);
  54 + } else {
55 storager.stopPlay(streamInfo); 55 storager.stopPlay(streamInfo);
56 streamInfo = cmder.playStreamCmd(device, channelId); 56 streamInfo = cmder.playStreamCmd(device, channelId);
57 } 57 }
@@ -60,34 +60,40 @@ public class PlayController { @@ -60,34 +60,40 @@ public class PlayController {
60 String streamId = String.format("%08x", Integer.parseInt(streamInfo.getSsrc())).toUpperCase(); 60 String streamId = String.format("%08x", Integer.parseInt(streamInfo.getSsrc())).toUpperCase();
61 // 等待推流, TODO 默认超时30s 61 // 等待推流, TODO 默认超时30s
62 boolean lockFlag = true; 62 boolean lockFlag = true;
  63 + boolean rtpPushed = false;
63 long startTime = System.currentTimeMillis(); 64 long startTime = System.currentTimeMillis();
  65 + JSONObject rtpInfo = null;
64 66
65 while (lockFlag) { 67 while (lockFlag) {
66 try { 68 try {
67 - if (System.currentTimeMillis() - startTime > 30 * 1000) { 69 + if (System.currentTimeMillis() - startTime > 60 * 1000) {
68 storager.stopPlay(streamInfo); 70 storager.stopPlay(streamInfo);
69 logger.info("播放等待超时"); 71 logger.info("播放等待超时");
70 - return new ResponseEntity<String>("timeout",HttpStatus.OK);  
71 - }else { 72 + return new ResponseEntity<String>("timeout", HttpStatus.OK);
  73 + } else {
72 streamInfo = storager.queryPlayByDevice(deviceId, channelId); 74 streamInfo = storager.queryPlayByDevice(deviceId, channelId);
73 - JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId);  
74 - if (rtpInfo != null && rtpInfo.getBoolean("exist") && streamInfo != null && streamInfo.getFlv() != null){  
75 - logger.info("RTP已推流,查询编码信息:"+streamInfo.getFlv()); 75 + if (!rtpPushed) {
  76 + logger.info("查询RTP推流信息...");
  77 + rtpInfo = zlmresTfulUtils.getRtpInfo(streamId);
  78 + }
  79 + if (rtpInfo != null && rtpInfo.getBoolean("exist") && streamInfo != null && streamInfo.getFlv() != null) {
  80 + logger.info("查询流编码信息:" + streamInfo.getFlv());
  81 + rtpPushed = true;
76 Thread.sleep(2000); 82 Thread.sleep(2000);
77 JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo("rtp", "rtmp", streamId); 83 JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo("rtp", "rtmp", streamId);
78 if (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online")) { 84 if (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online")) {
79 lockFlag = false; 85 lockFlag = false;
80 - logger.info("媒体编码信息已获取"); 86 + logger.info("编码信息已获取");
81 JSONArray tracks = mediaInfo.getJSONArray("tracks"); 87 JSONArray tracks = mediaInfo.getJSONArray("tracks");
82 streamInfo.setTracks(tracks); 88 streamInfo.setTracks(tracks);
83 storager.startPlay(streamInfo); 89 storager.startPlay(streamInfo);
84 - }else {  
85 - logger.info("媒体编码信息未获取,2秒后重试..."); 90 + } else {
  91 + logger.info("流编码信息未获取,2秒后重试...");
86 } 92 }
87 - }else { 93 + } else {
88 Thread.sleep(2000); 94 Thread.sleep(2000);
89 continue; 95 continue;
90 - }; 96 + }
91 } 97 }
92 } catch (InterruptedException e) { 98 } catch (InterruptedException e) {
93 e.printStackTrace(); 99 e.printStackTrace();
@@ -95,33 +101,35 @@ public class PlayController { @@ -95,33 +101,35 @@ public class PlayController {
95 } 101 }
96 102
97 if (logger.isDebugEnabled()) { 103 if (logger.isDebugEnabled()) {
98 - logger.debug(String.format("设备预览 API调用,deviceId:%s ,channelId:%s",deviceId, channelId));  
99 - logger.debug("设备预览 API调用,ssrc:"+streamInfo.getSsrc()+",ZLMedia streamId:"+Integer.toHexString(Integer.parseInt(streamInfo.getSsrc()))); 104 + logger.debug(String.format("设备预览 API调用,deviceId:%s ,channelId:%s", deviceId, channelId));
  105 + logger.debug("设备预览 API调用,ssrc:" + streamInfo.getSsrc() + ",ZLMedia streamId:"
  106 + + Integer.toHexString(Integer.parseInt(streamInfo.getSsrc())));
100 } 107 }
101 -  
102 - if(streamInfo!=null) {  
103 - return new ResponseEntity<String>(JSON.toJSONString(streamInfo),HttpStatus.OK); 108 +
  109 + if (streamInfo != null) {
  110 + return new ResponseEntity<String>(JSON.toJSONString(streamInfo), HttpStatus.OK);
104 } else { 111 } else {
105 logger.warn("设备预览API调用失败!"); 112 logger.warn("设备预览API调用失败!");
106 return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR); 113 return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR);
107 } 114 }
108 } 115 }
109 - 116 +
110 @PostMapping("/play/{ssrc}/stop") 117 @PostMapping("/play/{ssrc}/stop")
111 - public ResponseEntity<String> playStop(@PathVariable String ssrc){  
112 - 118 + public ResponseEntity<String> playStop(@PathVariable String ssrc) {
  119 +
113 cmder.streamByeCmd(ssrc); 120 cmder.streamByeCmd(ssrc);
114 StreamInfo streamInfo = storager.queryPlayBySSRC(ssrc); 121 StreamInfo streamInfo = storager.queryPlayBySSRC(ssrc);
115 - if (streamInfo == null) return new ResponseEntity<String>(HttpStatus.PAYMENT_REQUIRED); 122 + if (streamInfo == null)
  123 + return new ResponseEntity<String>(HttpStatus.PAYMENT_REQUIRED);
116 storager.stopPlay(streamInfo); 124 storager.stopPlay(streamInfo);
117 if (logger.isDebugEnabled()) { 125 if (logger.isDebugEnabled()) {
118 logger.debug(String.format("设备预览停止API调用,ssrc:%s", ssrc)); 126 logger.debug(String.format("设备预览停止API调用,ssrc:%s", ssrc));
119 } 127 }
120 -  
121 - if(ssrc!=null) { 128 +
  129 + if (ssrc != null) {
122 JSONObject json = new JSONObject(); 130 JSONObject json = new JSONObject();
123 json.put("ssrc", ssrc); 131 json.put("ssrc", ssrc);
124 - return new ResponseEntity<String>(json.toString(),HttpStatus.OK); 132 + return new ResponseEntity<String>(json.toString(), HttpStatus.OK);
125 } else { 133 } else {
126 logger.warn("设备预览停止API调用失败!"); 134 logger.warn("设备预览停止API调用失败!");
127 return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR); 135 return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR);
src/main/java/com/genersoft/iot/vmp/vmanager/playback/PlaybackController.java
@@ -52,7 +52,7 @@ public class PlaybackController { @@ -52,7 +52,7 @@ public class PlaybackController {
52 } 52 }
53 53
54 Device device = storager.queryVideoDevice(deviceId); 54 Device device = storager.queryVideoDevice(deviceId);
55 - StreamInfo streamInfo = storager.queryPlayBlackByDevice(deviceId, channelId); 55 + StreamInfo streamInfo = storager.queryPlaybackByDevice(deviceId, channelId);
56 56
57 if (streamInfo != null) { 57 if (streamInfo != null) {
58 cmder.streamByeCmd(streamInfo.getSsrc()); 58 cmder.streamByeCmd(streamInfo.getSsrc());
@@ -64,7 +64,7 @@ public class PlaybackController { @@ -64,7 +64,7 @@ public class PlaybackController {
64 // if (rtpInfo.getBoolean("exist")) { 64 // if (rtpInfo.getBoolean("exist")) {
65 // return new ResponseEntity<String>(JSON.toJSONString(streamInfo),HttpStatus.OK); 65 // return new ResponseEntity<String>(JSON.toJSONString(streamInfo),HttpStatus.OK);
66 // }else { 66 // }else {
67 -// storager.stopPlayBlack(streamInfo); 67 +// storager.stopPlayback(streamInfo);
68 // streamInfo = cmder.playbackStreamCmd(device, channelId, startTime, endTime); 68 // streamInfo = cmder.playbackStreamCmd(device, channelId, startTime, endTime);
69 // } 69 // }
70 // } 70 // }
@@ -77,29 +77,40 @@ public class PlaybackController { @@ -77,29 +77,40 @@ public class PlaybackController {
77 } 77 }
78 // 等待推流, TODO 默认超时15s 78 // 等待推流, TODO 默认超时15s
79 boolean lockFlag = true; 79 boolean lockFlag = true;
  80 + boolean rtpPushed = false;
80 long lockStartTime = System.currentTimeMillis(); 81 long lockStartTime = System.currentTimeMillis();
  82 + JSONObject rtpInfo = null;
  83 +
81 while (lockFlag) { 84 while (lockFlag) {
82 try { 85 try {
83 if (System.currentTimeMillis() - lockStartTime > 75 * 1000) { 86 if (System.currentTimeMillis() - lockStartTime > 75 * 1000) {
84 - storager.stopPlayBlack(streamInfo); 87 + storager.stopPlayback(streamInfo);
  88 + logger.info("播放等待超时");
85 return new ResponseEntity<String>("timeout",HttpStatus.OK); 89 return new ResponseEntity<String>("timeout",HttpStatus.OK);
86 }else { 90 }else {
87 - streamInfo = storager.queryPlayBlackByDevice(deviceId, channelId);  
88 - JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId);  
89 - if (rtpInfo != null && rtpInfo.getBoolean("exist") && streamInfo.getFlv() != null){ 91 + streamInfo = storager.queryPlaybackByDevice(deviceId, channelId);
  92 + if (!rtpPushed) {
  93 + logger.info("查询RTP推流信息...");
  94 + rtpInfo = zlmresTfulUtils.getRtpInfo(streamId);
  95 + }
  96 + if (rtpInfo != null && rtpInfo.getBoolean("exist") && streamInfo != null && streamInfo.getFlv() != null){
  97 + logger.info("查询流编码信息:"+streamInfo.getFlv());
  98 + rtpPushed = true;
  99 + Thread.sleep(2000);
90 JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo("rtp", "rtmp", streamId); 100 JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo("rtp", "rtmp", streamId);
91 if (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online")) { 101 if (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online")) {
92 lockFlag = false; 102 lockFlag = false;
  103 + logger.info("流编码信息已获取");
93 JSONArray tracks = mediaInfo.getJSONArray("tracks"); 104 JSONArray tracks = mediaInfo.getJSONArray("tracks");
94 streamInfo.setTracks(tracks); 105 streamInfo.setTracks(tracks);
95 - storager.startPlayBlack(streamInfo); 106 + storager.startPlayback(streamInfo);
96 }else { 107 }else {
97 - 108 + logger.info("流编码信息未获取,2秒后重试...");
98 } 109 }
99 }else { 110 }else {
100 Thread.sleep(2000); 111 Thread.sleep(2000);
101 continue; 112 continue;
102 - }; 113 + }
103 } 114 }
104 } catch (InterruptedException e) { 115 } catch (InterruptedException e) {
105 e.printStackTrace(); 116 e.printStackTrace();
web_src/src/components/gb28181/devicePlayer.vue
1 <template> 1 <template>
2 - <div id="devicePlayer">  
3 - <el-dialog title="视频播放" top="0" :close-on-click-modal="false" :visible.sync="showVideoDialog" :destroy-on-close="true" @close="close()">  
4 - <LivePlayer v-if="showVideoDialog" ref="videoPlayer" :videoUrl="videoUrl" :error="videoError" :hasaudio="hasaudio" fluent autoplay live ></LivePlayer>  
5 - <div id="shared" style="text-align: right; margin-top: 1rem;">  
6 - <el-tabs v-model="tabActiveName">  
7 - <el-tab-pane label="实时视频" name="media">  
8 - <div style="margin-bottom: 0.5rem;">  
9 -<!-- <el-button type="primary" size="small" @click="playRecord(true, '')">播放</el-button>-->  
10 -<!-- <el-button type="primary" size="small" @click="startRecord()">录制</el-button>-->  
11 -<!-- <el-button type="primary" size="small" @click="stopRecord()">停止录制</el-button>-->  
12 - </div>  
13 - <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;">  
14 - <span style="width: 5rem; line-height: 2.5rem; text-align: right;">播放地址:</span>  
15 - <el-input v-model="getPlayerShared.sharedUrl" :disabled="true" v-on:click.native="copySharedInfo(getPlayerShared.sharedUrl)"></el-input>  
16 - </div>  
17 - <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;">  
18 - <span style="width: 5rem; line-height: 2.5rem; text-align: right;">iframe:</span>  
19 - <el-input v-model="getPlayerShared.sharedIframe" :disabled="true" v-on:click.native="copySharedInfo(getPlayerShared.sharedIframe)"></el-input>  
20 - </div>  
21 - <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;">  
22 - <span style="width: 5rem; line-height: 2.5rem; text-align: right;">资源地址:</span>  
23 - <el-input v-model="getPlayerShared.sharedRtmp" :disabled="true" v-on:click.native="copySharedInfo(getPlayerShared.sharedRtmp)"></el-input>  
24 - </div>  
25 - </el-tab-pane>  
26 - <!--{"code":0,"data":{"paths":["22-29-30.mp4"],"rootPath":"/home/kkkkk/Documents/ZLMediaKit/release/linux/Debug/www/record/hls/kkkkk/2020-05-11/"}}-->  
27 - <el-tab-pane label="录像查询" name="record">  
28 - <el-date-picker size="mini" v-model="videoHistory.date" type="date" value-format="yyyy-MM-dd" placeholder="日期"  
29 - @change="queryRecords()"></el-date-picker>  
30 -<!-- <el-slider style="margin: 0 1rem 1rem 1rem;"-->  
31 -<!-- v-model="timeVal"-->  
32 -<!-- :min="timeMin"-->  
33 -<!-- :max="timeMax"-->  
34 -<!-- :step="5"-->  
35 -<!-- :marks="getTimeMakrs()"-->  
36 -<!-- :format-tooltip="formatTooltip">-->  
37 -<!-- </el-slider>-->  
38 -<!-- <range-slider :min="timeMin"-->  
39 -<!-- :max="timeMax"-->  
40 -<!-- :step="5"></range-slider>--> 2 +<div id="devicePlayer">
  3 + <el-dialog title="视频播放" top="0" :close-on-click-modal="false" :visible.sync="showVideoDialog" :destroy-on-close="true" @close="close()">
  4 + <LivePlayer v-if="showVideoDialog" ref="videoPlayer" :videoUrl="videoUrl" :error="videoError" :hasaudio="hasaudio" fluent autoplay live></LivePlayer>
  5 + <div id="shared" style="text-align: right; margin-top: 1rem;">
  6 + <el-tabs v-model="tabActiveName">
  7 + <el-tab-pane label="实时视频" name="media">
  8 + <div style="margin-bottom: 0.5rem;">
  9 + <!-- <el-button type="primary" size="small" @click="playRecord(true, '')">播放</el-button>-->
  10 + <!-- <el-button type="primary" size="small" @click="startRecord()">录制</el-button>-->
  11 + <!-- <el-button type="primary" size="small" @click="stopRecord()">停止录制</el-button>-->
  12 + </div>
  13 + <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;">
  14 + <span style="width: 5rem; line-height: 2.5rem; text-align: right;">播放地址:</span>
  15 + <el-input v-model="getPlayerShared.sharedUrl" :disabled="true" v-on:click.native="copySharedInfo(getPlayerShared.sharedUrl)"></el-input>
  16 + </div>
  17 + <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;">
  18 + <span style="width: 5rem; line-height: 2.5rem; text-align: right;">iframe:</span>
  19 + <el-input v-model="getPlayerShared.sharedIframe" :disabled="true" v-on:click.native="copySharedInfo(getPlayerShared.sharedIframe)"></el-input>
  20 + </div>
  21 + <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;">
  22 + <span style="width: 5rem; line-height: 2.5rem; text-align: right;">资源地址:</span>
  23 + <el-input v-model="getPlayerShared.sharedRtmp" :disabled="true" v-on:click.native="copySharedInfo(getPlayerShared.sharedRtmp)"></el-input>
  24 + </div>
  25 + </el-tab-pane>
  26 + <!--{"code":0,"data":{"paths":["22-29-30.mp4"],"rootPath":"/home/kkkkk/Documents/ZLMediaKit/release/linux/Debug/www/record/hls/kkkkk/2020-05-11/"}}-->
  27 + <el-tab-pane label="录像查询" name="record">
  28 + <el-date-picker size="mini" v-model="videoHistory.date" type="date" value-format="yyyy-MM-dd" placeholder="日期" @change="queryRecords()"></el-date-picker>
  29 + <!-- <el-slider style="margin: 0 1rem 1rem 1rem;"-->
  30 + <!-- v-model="timeVal"-->
  31 + <!-- :min="timeMin"-->
  32 + <!-- :max="timeMax"-->
  33 + <!-- :step="5"-->
  34 + <!-- :marks="getTimeMakrs()"-->
  35 + <!-- :format-tooltip="formatTooltip">-->
  36 + <!-- </el-slider>-->
  37 + <!-- <range-slider :min="timeMin"-->
  38 + <!-- :max="timeMax"-->
  39 + <!-- :step="5"></range-slider>-->
41 40
42 -<!-- <el-date-picker v-model="videoHistory.endTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss" placeholder="结束时间"-->  
43 -<!-- @change="recordList()"></el-date-picker>-->  
44 - <el-table :data="videoHistory.searchHistoryResult" height="150" v-load="recordsLoading">  
45 - <el-table-column label="名称" prop="name"></el-table-column>  
46 - <el-table-column label="文件" prop="filePath"></el-table-column>  
47 - <el-table-column label="开始时间" prop="startTime" :formatter="timeFormatter"></el-table-column>  
48 - <el-table-column label="结束时间" prop="endTime" :formatter="timeFormatter"></el-table-column> 41 + <!-- <el-date-picker v-model="videoHistory.endTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss" placeholder="结束时间"-->
  42 + <!-- @change="recordList()"></el-date-picker>-->
  43 + <el-table :data="videoHistory.searchHistoryResult" height="150" v-load="recordsLoading">
  44 + <el-table-column label="名称" prop="name"></el-table-column>
  45 + <el-table-column label="文件" prop="filePath"></el-table-column>
  46 + <el-table-column label="开始时间" prop="startTime" :formatter="timeFormatter"></el-table-column>
  47 + <el-table-column label="结束时间" prop="endTime" :formatter="timeFormatter"></el-table-column>
49 48
50 - <el-table-column label="操作" >  
51 - <template slot-scope="scope">  
52 - <el-button icon="el-icon-video-play" size="mini" @click="playRecord(scope.row)">播放</el-button>  
53 - </template>  
54 - </el-table-column>  
55 - </el-table>  
56 - </el-tab-pane>  
57 - <!--遥控界面-->  
58 - <el-tab-pane label="云台控制" name="control">  
59 - <div style="display: flex; justify-content: center;">  
60 - <div class="control-wrapper">  
61 - <div class="control-btn control-top" @mousedown="ptzCamera(0, 1, 0)" @mouseup="ptzCamera(0, 0, 0)">  
62 - <i class="el-icon-caret-top"></i>  
63 - <div class="control-inner-btn control-inner"></div>  
64 - </div>  
65 - <div class="control-btn control-left" @mousedown="ptzCamera(1, 0, 0)" @mouseup="ptzCamera(0, 0, 0)">  
66 - <i class="el-icon-caret-left"></i>  
67 - <div class="control-inner-btn control-inner"></div>  
68 - </div>  
69 - <div class="control-btn control-bottom" @mousedown="ptzCamera(0, 2, 0)" @mouseup="ptzCamera(0, 0, 0)">  
70 - <i class="el-icon-caret-bottom"></i>  
71 - <div class="control-inner-btn control-inner"></div>  
72 - </div>  
73 - <div class="control-btn control-right" @mousedown="ptzCamera(2, 0, 0)" @mouseup="ptzCamera(0, 0, 0)">  
74 - <i class="el-icon-caret-right"></i>  
75 - <div class="control-inner-btn control-inner"></div>  
76 - </div>  
77 - <div class="control-round">  
78 - <div class="control-round-inner"><i class="fa fa-pause-circle"></i></div>  
79 - </div>  
80 - <div style="position: absolute; left: 7.25rem; top: 1.25rem" @mousedown="ptzCamera(0, 0, 2)" @mouseup="ptzCamera(0, 0, 0)"><i  
81 - class="el-icon-zoom-in" style="font-size: 1.875rem;"></i></div>  
82 - <div style="position: absolute; left: 7.25rem; top: 3.25rem; font-size: 1.875rem;" @mousedown="ptzCamera(0, 0, 1)"  
83 - @mouseup="ptzCamera(0, 0, 0)"><i class="el-icon-zoom-out"></i></div>  
84 - </div>  
85 - </div> 49 + <el-table-column label="操作">
  50 + <template slot-scope="scope">
  51 + <el-button icon="el-icon-video-play" size="mini" @click="playRecord(scope.row)">播放</el-button>
  52 + </template>
  53 + </el-table-column>
  54 + </el-table>
  55 + </el-tab-pane>
  56 + <!--遥控界面-->
  57 + <el-tab-pane label="云台控制" name="control">
  58 + <div style="display: flex; justify-content: center;">
  59 + <div class="control-wrapper">
  60 + <div class="control-btn control-top" @mousedown="ptzCamera(0, 1, 0)" @mouseup="ptzCamera(0, 0, 0)">
  61 + <i class="el-icon-caret-top"></i>
  62 + <div class="control-inner-btn control-inner"></div>
  63 + </div>
  64 + <div class="control-btn control-left" @mousedown="ptzCamera(1, 0, 0)" @mouseup="ptzCamera(0, 0, 0)">
  65 + <i class="el-icon-caret-left"></i>
  66 + <div class="control-inner-btn control-inner"></div>
  67 + </div>
  68 + <div class="control-btn control-bottom" @mousedown="ptzCamera(0, 2, 0)" @mouseup="ptzCamera(0, 0, 0)">
  69 + <i class="el-icon-caret-bottom"></i>
  70 + <div class="control-inner-btn control-inner"></div>
  71 + </div>
  72 + <div class="control-btn control-right" @mousedown="ptzCamera(2, 0, 0)" @mouseup="ptzCamera(0, 0, 0)">
  73 + <i class="el-icon-caret-right"></i>
  74 + <div class="control-inner-btn control-inner"></div>
  75 + </div>
  76 + <div class="control-round">
  77 + <div class="control-round-inner"><i class="fa fa-pause-circle"></i></div>
  78 + </div>
  79 + <div style="position: absolute; left: 7.25rem; top: 1.25rem" @mousedown="ptzCamera(0, 0, 2)" @mouseup="ptzCamera(0, 0, 0)"><i class="el-icon-zoom-in" style="font-size: 1.875rem;"></i></div>
  80 + <div style="position: absolute; left: 7.25rem; top: 3.25rem; font-size: 1.875rem;" @mousedown="ptzCamera(0, 0, 1)" @mouseup="ptzCamera(0, 0, 0)"><i class="el-icon-zoom-out"></i></div>
  81 + </div>
  82 + </div>
86 83
87 - </el-tab-pane>  
88 - </el-tabs>  
89 - </div>  
90 - </el-dialog>  
91 - </div> 84 + </el-tab-pane>
  85 + </el-tabs>
  86 + </div>
  87 + </el-dialog>
  88 +</div>
92 </template> 89 </template>
93 90
94 <script> 91 <script>
95 - import LivePlayer from '@liveqing/liveplayer'  
96 - export default {  
97 - name: 'devicePlayer',  
98 - props: {},  
99 - components: {  
100 - LivePlayer  
101 - },  
102 - computed: {  
103 - getPlayerShared: function() { 92 +import LivePlayer from '@liveqing/liveplayer'
  93 +export default {
  94 + name: 'devicePlayer',
  95 + props: {},
  96 + components: {
  97 + LivePlayer
  98 + },
  99 + computed: {
  100 + getPlayerShared: function () {
  101 + return {
  102 + sharedUrl: window.location.host + '/' + this.videoUrl,
  103 + sharedIframe: '<iframe src="' + window.location.host + '/' + this.videoUrl + '"></iframe>',
  104 + sharedRtmp: this.videoUrl
  105 + };
  106 + }
  107 + },
  108 + created() {},
  109 + data() {
104 return { 110 return {
105 - sharedUrl: window.location.host + '/' + this.videoUrl,  
106 - sharedIframe: '<iframe src="' + window.location.host + '/' + this.videoUrl + '"></iframe>',  
107 - sharedRtmp: this.videoUrl  
108 - };  
109 - }  
110 - },  
111 - created() {  
112 - },  
113 - data() {  
114 - return {  
115 - video:'http://lndxyj.iqilu.com/public/upload/2019/10/14/8c001ea0c09cdc59a57829dabc8010fa.mp4',  
116 - videoUrl: '',  
117 - videoHistory: {  
118 - date: '',  
119 - searchHistoryResult: [] //媒体流历史记录搜索结果  
120 - },  
121 - timeMakrs:{  
122 - // 0 : "0:00",  
123 - // // 60 : "1:00",  
124 - // 120 : "2:00",  
125 - // // 180 : "3:00",  
126 - // 240 : "4:00",  
127 - // // 300 : "5:00",  
128 - // 360 : "6:00",  
129 - // // 420 : "7:00",  
130 - // 480 : "8:00",  
131 - // 540 : "9:00",  
132 - 600: "10:00",  
133 - // 660 : "11:00",  
134 - 720 : "12:00",  
135 - // 780 : "13:00",  
136 - 840 : "14:00",  
137 - // 900 : "15:00",  
138 - 960 : "16:00",  
139 - // 1020 : "17:00",  
140 - 1080 : "18:00",  
141 - // 1140 : "19:00",  
142 - // 1200 : "20:00",  
143 - // // 1260 : "21:00",  
144 - // 1320 : "22:00",  
145 - // // 1380 : "23:00",  
146 - // 1440 : "24:00"  
147 - },  
148 - showVideoDialog: false,  
149 - ssrc: '',  
150 - deviceId: '',  
151 - channelId: '',  
152 - tabActiveName: 'media',  
153 - hasaudio: false,  
154 - loadingRecords: false,  
155 - recordsLoading: false,  
156 - timeVal: 0,  
157 - timeMin: 0,  
158 - timeMax: 1440, 111 + video: 'http://lndxyj.iqilu.com/public/upload/2019/10/14/8c001ea0c09cdc59a57829dabc8010fa.mp4',
  112 + videoUrl: '',
  113 + videoHistory: {
  114 + date: '',
  115 + searchHistoryResult: [] //媒体流历史记录搜索结果
  116 + },
  117 + timeMakrs: {
  118 + // 0 : "0:00",
  119 + // // 60 : "1:00",
  120 + // 120 : "2:00",
  121 + // // 180 : "3:00",
  122 + // 240 : "4:00",
  123 + // // 300 : "5:00",
  124 + // 360 : "6:00",
  125 + // // 420 : "7:00",
  126 + // 480 : "8:00",
  127 + // 540 : "9:00",
  128 + 600: "10:00",
  129 + // 660 : "11:00",
  130 + 720: "12:00",
  131 + // 780 : "13:00",
  132 + 840: "14:00",
  133 + // 900 : "15:00",
  134 + 960: "16:00",
  135 + // 1020 : "17:00",
  136 + 1080: "18:00",
  137 + // 1140 : "19:00",
  138 + // 1200 : "20:00",
  139 + // // 1260 : "21:00",
  140 + // 1320 : "22:00",
  141 + // // 1380 : "23:00",
  142 + // 1440 : "24:00"
  143 + },
  144 + showVideoDialog: false,
  145 + ssrc: '',
  146 + deviceId: '',
  147 + channelId: '',
  148 + tabActiveName: 'media',
  149 + hasaudio: false,
  150 + loadingRecords: false,
  151 + recordsLoading: false,
  152 + timeVal: 0,
  153 + timeMin: 0,
  154 + timeMax: 1440,
159 155
160 - };  
161 - },  
162 - methods: {  
163 - openDialog: function (tab, deviceId, channelId, param) {  
164 - this.tabActiveName = tab;  
165 - this.channelId = channelId;  
166 - this.deviceId = deviceId;  
167 - this.ssrc = "";  
168 - this.videoUrl = ""  
169 - if (!!this.$refs.videoPlayer) {  
170 - this.$refs.videoPlayer.pause();  
171 - } 156 + };
  157 + },
  158 + methods: {
  159 + openDialog: function (tab, deviceId, channelId, param) {
  160 + this.tabActiveName = tab;
  161 + this.channelId = channelId;
  162 + this.deviceId = deviceId;
  163 + this.ssrc = "";
  164 + this.videoUrl = ""
  165 + if (!!this.$refs.videoPlayer) {
  166 + this.$refs.videoPlayer.pause();
  167 + }
172 168
173 - switch(tab) {  
174 - case "media":  
175 - this.play(param.streamInfo, param.hasAudio)  
176 - break;  
177 - case "record":  
178 - this.showVideoDialog = true; 169 + switch (tab) {
  170 + case "media":
  171 + this.play(param.streamInfo, param.hasAudio)
  172 + break;
  173 + case "record":
  174 + this.showVideoDialog = true;
179 175
180 - this.videoHistory.date = param.date;  
181 - this.queryRecords()  
182 - break;  
183 - case "control":  
184 - break;  
185 - }  
186 - },  
187 - timeAxisSelTime:function (val) {  
188 - console.log(val)  
189 - },  
190 - getTimeMakrs(){  
191 - return this.timeMakrs;  
192 - }, 176 + this.videoHistory.date = param.date;
  177 + this.queryRecords()
  178 + break;
  179 + case "control":
  180 + break;
  181 + }
  182 + },
  183 + timeAxisSelTime: function (val) {
  184 + console.log(val)
  185 + },
  186 + getTimeMakrs() {
  187 + return this.timeMakrs;
  188 + },
193 play: function (streamInfo, hasAudio) { 189 play: function (streamInfo, hasAudio) {
194 this.hasaudio = hasAudio; 190 this.hasaudio = hasAudio;
195 // 根据媒体流信息二次判断 191 // 根据媒体流信息二次判断
@@ -236,276 +232,278 @@ @@ -236,276 +232,278 @@
236 ); 232 );
237 }, 233 },
238 234
239 - queryRecords: function() {  
240 - if (!this.videoHistory.date) {  
241 - return;  
242 - }  
243 - this.recordsLoading = true;  
244 - let that = this;  
245 - var startTime = this.videoHistory.date + " 00:00:00";  
246 - var endTime = this.videoHistory.date + " 23:59:59";  
247 - this.$axios({  
248 - method: 'get',  
249 - url: '/api/record/' + this.deviceId + '/' + this.channelId + '?startTime=' + startTime + '&endTime=' + endTime  
250 - }).then(function(res) {  
251 - // 处理时间信息  
252 - that.videoHistory.searchHistoryResult = res.data.recordList;  
253 - that.recordsLoading = false;  
254 - }).catch(function(e) {  
255 - // that.videoHistory.searchHistoryResult = falsificationData.recordData;  
256 - }); 235 + queryRecords: function () {
  236 + if (!this.videoHistory.date) {
  237 + return;
  238 + }
  239 + this.recordsLoading = true;
  240 + this.videoHistory.searchHistoryResult = [];
  241 + let that = this;
  242 + var startTime = this.videoHistory.date + " 00:00:00";
  243 + var endTime = this.videoHistory.date + " 23:59:59";
  244 + this.$axios({
  245 + method: 'get',
  246 + url: '/api/record/' + this.deviceId + '/' + this.channelId + '?startTime=' + startTime + '&endTime=' + endTime
  247 + }).then(function (res) {
  248 + // 处理时间信息
  249 + that.videoHistory.searchHistoryResult = res.data.recordList;
  250 + that.recordsLoading = false;
  251 + }).catch(function (e) {
  252 + console.log(e.message);
  253 + // that.videoHistory.searchHistoryResult = falsificationData.recordData;
  254 + });
257 255
258 - },  
259 - onTimeChange: function (video) {  
260 - // this.queryRecords()  
261 - },  
262 - playRecord: function(row) {  
263 - let that = this;  
264 - if (that.ssrc != "") {  
265 - that.stopPlayRecord(function (){  
266 - that.ssrc = "",  
267 - that.playRecord(row);  
268 - })  
269 - }else {  
270 - this.$axios({  
271 - method: 'get',  
272 - url: '/api/playback/' + this.deviceId + '/' + this.channelId + '?startTime=' + row.startTime + '&endTime=' +  
273 - row.endTime  
274 - }).then(function(res) {  
275 - var streamInfo = res.data;  
276 - that.ssrc = streamInfo.ssrc;  
277 - that.videoUrl = streamInfo.ws_flv;  
278 - });  
279 - }  
280 - },  
281 - stopPlayRecord: function (callback) {  
282 - this.$refs.videoPlayer.pause();  
283 - this.videoUrl = '';  
284 - this.$axios({  
285 - method: 'get',  
286 - url: '/api/playback/' + this.ssrc + '/stop'  
287 - }).then(function(res) {  
288 - if (callback) callback()  
289 - });  
290 - },  
291 - ptzCamera: function(leftRight, upDown, zoom) {  
292 - console.log('云台控制:' + leftRight + ' : ' + upDown + " : " + zoom);  
293 - let that = this;  
294 - this.$axios({  
295 - method: 'post',  
296 - url: '/api/ptz/' + this.deviceId + '/' + this.channelId + '?leftRight=' + leftRight + '&upDown=' + upDown +  
297 - '&inOut=' + zoom + '&moveSpeed=50&zoomSpeed=50'  
298 - }).then(function(res) {});  
299 - },  
300 - //////////////////////播放器事件处理//////////////////////////  
301 - videoError:function(e){  
302 - console.log("播放器错误:"+JSON.stringify(e));  
303 - },  
304 - formatTooltip:function(val) {  
305 - var h = parseInt(val/60);  
306 - var hStr = h< 10 ? ("0" + h):h;  
307 - var s = val%60;  
308 - var sStr = s< 10 ? ("0" + s):s;  
309 - return h + ":" + sStr;  
310 - },  
311 - timeFormatter: function (row, column, cellValue, index) {  
312 - return cellValue.split( " ")[1];  
313 - },  
314 - mergeTime: function (timeArray) {  
315 - var resultArray = [];  
316 - for (let i = 0; i < timeArray.length; i++) {  
317 - var startTime = new Date(timeArray[i].startTime);  
318 - var endTime = new Date(timeArray[i].endTime);  
319 - if (i ==0) {  
320 - resultArray[0] = {  
321 - startTime: startTime,  
322 - endTime: endTime 256 + },
  257 + onTimeChange: function (video) {
  258 + // this.queryRecords()
  259 + },
  260 + playRecord: function (row) {
  261 + let that = this;
  262 + if (that.ssrc != "") {
  263 + that.stopPlayRecord(function () {
  264 + that.ssrc = "",
  265 + that.playRecord(row);
  266 + })
  267 + } else {
  268 + this.$axios({
  269 + method: 'get',
  270 + url: '/api/playback/' + this.deviceId + '/' + this.channelId + '?startTime=' + row.startTime + '&endTime=' +
  271 + row.endTime
  272 + }).then(function (res) {
  273 + var streamInfo = res.data;
  274 + that.ssrc = streamInfo.ssrc;
  275 + that.videoUrl = streamInfo.ws_flv;
  276 + });
323 } 277 }
324 - }  
325 - for (let j = 0; j < resultArray.length; j++) {  
326 - if (startTime > resultArray[j].endTime ) { // 合并  
327 - if (startTime - resultArray[j].endTime <= 1000){  
328 - resultArray[j].endTime = endTime;  
329 - }else {  
330 - resultArray[resultArray.length] = {  
331 - startTime: startTime,  
332 - endTime: endTime 278 + },
  279 + stopPlayRecord: function (callback) {
  280 + this.$refs.videoPlayer.pause();
  281 + this.videoUrl = '';
  282 + this.$axios({
  283 + method: 'get',
  284 + url: '/api/playback/' + this.ssrc + '/stop'
  285 + }).then(function (res) {
  286 + if (callback) callback()
  287 + });
  288 + },
  289 + ptzCamera: function (leftRight, upDown, zoom) {
  290 + console.log('云台控制:' + leftRight + ' : ' + upDown + " : " + zoom);
  291 + let that = this;
  292 + this.$axios({
  293 + method: 'post',
  294 + url: '/api/ptz/' + this.deviceId + '/' + this.channelId + '?leftRight=' + leftRight + '&upDown=' + upDown +
  295 + '&inOut=' + zoom + '&moveSpeed=50&zoomSpeed=50'
  296 + }).then(function (res) {});
  297 + },
  298 + //////////////////////播放器事件处理//////////////////////////
  299 + videoError: function (e) {
  300 + console.log("播放器错误:" + JSON.stringify(e));
  301 + },
  302 + formatTooltip: function (val) {
  303 + var h = parseInt(val / 60);
  304 + var hStr = h < 10 ? ("0" + h) : h;
  305 + var s = val % 60;
  306 + var sStr = s < 10 ? ("0" + s) : s;
  307 + return h + ":" + sStr;
  308 + },
  309 + timeFormatter: function (row, column, cellValue, index) {
  310 + return cellValue.split(" ")[1];
  311 + },
  312 + mergeTime: function (timeArray) {
  313 + var resultArray = [];
  314 + for (let i = 0; i < timeArray.length; i++) {
  315 + var startTime = new Date(timeArray[i].startTime);
  316 + var endTime = new Date(timeArray[i].endTime);
  317 + if (i == 0) {
  318 + resultArray[0] = {
  319 + startTime: startTime,
  320 + endTime: endTime
  321 + }
333 } 322 }
334 - }  
335 - }else if(resultArray[j].startTime > endTime ) { // 合并  
336 - if (resultArray[j].startTime - endTime <= 1000) {  
337 - resultArray[j].startTime = startTime;  
338 - }else {  
339 - resultArray[resultArray.length] = {  
340 - startTime: startTime,  
341 - endTime: endTime 323 + for (let j = 0; j < resultArray.length; j++) {
  324 + if (startTime > resultArray[j].endTime) { // 合并
  325 + if (startTime - resultArray[j].endTime <= 1000) {
  326 + resultArray[j].endTime = endTime;
  327 + } else {
  328 + resultArray[resultArray.length] = {
  329 + startTime: startTime,
  330 + endTime: endTime
  331 + }
  332 + }
  333 + } else if (resultArray[j].startTime > endTime) { // 合并
  334 + if (resultArray[j].startTime - endTime <= 1000) {
  335 + resultArray[j].startTime = startTime;
  336 + } else {
  337 + resultArray[resultArray.length] = {
  338 + startTime: startTime,
  339 + endTime: endTime
  340 + }
  341 + }
  342 + }
342 } 343 }
343 - }  
344 } 344 }
345 - } 345 + console.log(resultArray)
  346 + return resultArray;
346 } 347 }
347 - console.log(resultArray)  
348 - return resultArray;  
349 - }  
350 - }  
351 - }; 348 + }
  349 +};
352 </script> 350 </script>
353 351
354 <style> 352 <style>
355 - .control-wrapper {  
356 - position: relative;  
357 - width: 6.25rem;  
358 - height: 6.25rem;  
359 - max-width: 6.25rem;  
360 - max-height: 6.25rem;  
361 - margin: 0 auto;  
362 - border-radius: 100%;  
363 - float: left;  
364 - } 353 +.control-wrapper {
  354 + position: relative;
  355 + width: 6.25rem;
  356 + height: 6.25rem;
  357 + max-width: 6.25rem;
  358 + max-height: 6.25rem;
  359 + margin: 0 auto;
  360 + border-radius: 100%;
  361 + float: left;
  362 +}
365 363
366 - .control-btn {  
367 - display: flex;  
368 - justify-content: center;  
369 - position: absolute;  
370 - width: 44%;  
371 - height: 44%;  
372 - border-radius: 5px;  
373 - border: 1px solid #78aee4;  
374 - box-sizing: border-box;  
375 - transition: all 0.3s linear;  
376 - } 364 +.control-btn {
  365 + display: flex;
  366 + justify-content: center;
  367 + position: absolute;
  368 + width: 44%;
  369 + height: 44%;
  370 + border-radius: 5px;
  371 + border: 1px solid #78aee4;
  372 + box-sizing: border-box;
  373 + transition: all 0.3s linear;
  374 +}
377 375
378 - .control-btn i {  
379 - font-size: 20px;  
380 - color: #78aee4;  
381 - display: flex;  
382 - justify-content: center;  
383 - align-items: center;  
384 - } 376 +.control-btn i {
  377 + font-size: 20px;
  378 + color: #78aee4;
  379 + display: flex;
  380 + justify-content: center;
  381 + align-items: center;
  382 +}
385 383
386 - .control-round {  
387 - position: absolute;  
388 - top: 21%;  
389 - left: 21%;  
390 - width: 58%;  
391 - height: 58%;  
392 - background: #fff;  
393 - border-radius: 100%;  
394 - } 384 +.control-round {
  385 + position: absolute;
  386 + top: 21%;
  387 + left: 21%;
  388 + width: 58%;
  389 + height: 58%;
  390 + background: #fff;
  391 + border-radius: 100%;
  392 +}
395 393
396 - .control-round-inner {  
397 - position: absolute;  
398 - left: 15%;  
399 - top: 15%;  
400 - display: flex;  
401 - justify-content: center;  
402 - align-items: center;  
403 - width: 70%;  
404 - height: 70%;  
405 - font-size: 40px;  
406 - color: #78aee4;  
407 - border: 1px solid #78aee4;  
408 - border-radius: 100%;  
409 - transition: all 0.3s linear;  
410 - } 394 +.control-round-inner {
  395 + position: absolute;
  396 + left: 15%;
  397 + top: 15%;
  398 + display: flex;
  399 + justify-content: center;
  400 + align-items: center;
  401 + width: 70%;
  402 + height: 70%;
  403 + font-size: 40px;
  404 + color: #78aee4;
  405 + border: 1px solid #78aee4;
  406 + border-radius: 100%;
  407 + transition: all 0.3s linear;
  408 +}
411 409
412 - .control-inner-btn {  
413 - position: absolute;  
414 - width: 60%;  
415 - height: 60%;  
416 - background: #fafafa;  
417 - } 410 +.control-inner-btn {
  411 + position: absolute;
  412 + width: 60%;
  413 + height: 60%;
  414 + background: #fafafa;
  415 +}
418 416
419 - .control-top {  
420 - top: -8%;  
421 - left: 27%;  
422 - transform: rotate(-45deg);  
423 - border-radius: 5px 100% 5px 0;  
424 - } 417 +.control-top {
  418 + top: -8%;
  419 + left: 27%;
  420 + transform: rotate(-45deg);
  421 + border-radius: 5px 100% 5px 0;
  422 +}
425 423
426 - .control-top i {  
427 - transform: rotate(45deg);  
428 - border-radius: 5px 100% 5px 0;  
429 - } 424 +.control-top i {
  425 + transform: rotate(45deg);
  426 + border-radius: 5px 100% 5px 0;
  427 +}
430 428
431 - .control-top .control-inner {  
432 - left: -1px;  
433 - bottom: 0;  
434 - border-top: 1px solid #78aee4;  
435 - border-right: 1px solid #78aee4;  
436 - border-radius: 0 100% 0 0;  
437 - } 429 +.control-top .control-inner {
  430 + left: -1px;
  431 + bottom: 0;
  432 + border-top: 1px solid #78aee4;
  433 + border-right: 1px solid #78aee4;
  434 + border-radius: 0 100% 0 0;
  435 +}
438 436
439 - .control-top .fa {  
440 - transform: rotate(45deg) translateY(-7px);  
441 - } 437 +.control-top .fa {
  438 + transform: rotate(45deg) translateY(-7px);
  439 +}
442 440
443 - .control-left {  
444 - top: 27%;  
445 - left: -8%;  
446 - transform: rotate(45deg);  
447 - border-radius: 5px 0 5px 100%;  
448 - } 441 +.control-left {
  442 + top: 27%;
  443 + left: -8%;
  444 + transform: rotate(45deg);
  445 + border-radius: 5px 0 5px 100%;
  446 +}
449 447
450 - .control-left i {  
451 - transform: rotate(-45deg);  
452 - } 448 +.control-left i {
  449 + transform: rotate(-45deg);
  450 +}
453 451
454 - .control-left .control-inner {  
455 - right: -1px;  
456 - top: -1px;  
457 - border-bottom: 1px solid #78aee4;  
458 - border-left: 1px solid #78aee4;  
459 - border-radius: 0 0 0 100%;  
460 - } 452 +.control-left .control-inner {
  453 + right: -1px;
  454 + top: -1px;
  455 + border-bottom: 1px solid #78aee4;
  456 + border-left: 1px solid #78aee4;
  457 + border-radius: 0 0 0 100%;
  458 +}
461 459
462 - .control-left .fa {  
463 - transform: rotate(-45deg) translateX(-7px);  
464 - } 460 +.control-left .fa {
  461 + transform: rotate(-45deg) translateX(-7px);
  462 +}
465 463
466 - .control-right {  
467 - top: 27%;  
468 - right: -8%;  
469 - transform: rotate(45deg);  
470 - border-radius: 5px 100% 5px 0;  
471 - } 464 +.control-right {
  465 + top: 27%;
  466 + right: -8%;
  467 + transform: rotate(45deg);
  468 + border-radius: 5px 100% 5px 0;
  469 +}
472 470
473 - .control-right i {  
474 - transform: rotate(-45deg);  
475 - } 471 +.control-right i {
  472 + transform: rotate(-45deg);
  473 +}
476 474
477 - .control-right .control-inner {  
478 - left: -1px;  
479 - bottom: -1px;  
480 - border-top: 1px solid #78aee4;  
481 - border-right: 1px solid #78aee4;  
482 - border-radius: 0 100% 0 0;  
483 - } 475 +.control-right .control-inner {
  476 + left: -1px;
  477 + bottom: -1px;
  478 + border-top: 1px solid #78aee4;
  479 + border-right: 1px solid #78aee4;
  480 + border-radius: 0 100% 0 0;
  481 +}
484 482
485 - .control-right .fa {  
486 - transform: rotate(-45deg) translateX(7px);  
487 - } 483 +.control-right .fa {
  484 + transform: rotate(-45deg) translateX(7px);
  485 +}
488 486
489 - .control-bottom {  
490 - left: 27%;  
491 - bottom: -8%;  
492 - transform: rotate(45deg);  
493 - border-radius: 0 5px 100% 5px;  
494 - } 487 +.control-bottom {
  488 + left: 27%;
  489 + bottom: -8%;
  490 + transform: rotate(45deg);
  491 + border-radius: 0 5px 100% 5px;
  492 +}
495 493
496 - .control-bottom i {  
497 - transform: rotate(-45deg);  
498 - } 494 +.control-bottom i {
  495 + transform: rotate(-45deg);
  496 +}
499 497
500 - .control-bottom .control-inner {  
501 - top: -1px;  
502 - left: -1px;  
503 - border-bottom: 1px solid #78aee4;  
504 - border-right: 1px solid #78aee4;  
505 - border-radius: 0 0 100% 0;  
506 - } 498 +.control-bottom .control-inner {
  499 + top: -1px;
  500 + left: -1px;
  501 + border-bottom: 1px solid #78aee4;
  502 + border-right: 1px solid #78aee4;
  503 + border-radius: 0 0 100% 0;
  504 +}
507 505
508 - .control-bottom .fa {  
509 - transform: rotate(-45deg) translateY(7px);  
510 - } 506 +.control-bottom .fa {
  507 + transform: rotate(-45deg) translateY(7px);
  508 +}
511 </style> 509 </style>