Merge remote-tracking branch 'origin/master' into wvp-28181-2.0
# Conflicts: # README.md # src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java # src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java # src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java # src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java # src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java # src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHTTPProxyController.java # src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java # src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java # src/main/java/com/genersoft/iot/vmp/storager/jdbc/VideoManagerJdbcStoragerImpl.java # src/main/java/com/genersoft/iot/vmp/storager/redis/VideoManagerRedisStoragerImpl.java # src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java # src/main/java/com/genersoft/iot/vmp/vmanager/playback/PlaybackController.java # src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java # src/main/java/com/genersoft/iot/vmp/web/ApiStreamController.java # src/main/resources/application-dev.yml # web_src/src/components/gb28181/devicePlayer.vue
This commit is contained in:
@@ -1,22 +1,17 @@
|
||||
package com.genersoft.iot.vmp.web;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.genersoft.iot.vmp.common.PageResult;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||
import com.genersoft.iot.vmp.vmanager.device.DeviceController;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
@@ -65,12 +60,12 @@ public class ApiDeviceController {
|
||||
JSONObject result = new JSONObject();
|
||||
List<Device> devices;
|
||||
if (start == null || limit ==null) {
|
||||
devices = storager.queryVideoDeviceList(null);
|
||||
devices = storager.queryVideoDeviceList();
|
||||
result.put("DeviceCount", devices.size());
|
||||
}else {
|
||||
PageResult<Device> deviceList = storager.queryVideoDeviceList(null, start/limit, limit);
|
||||
PageInfo<Device> deviceList = storager.queryVideoDeviceList(start/limit, limit);
|
||||
result.put("DeviceCount", deviceList.getTotal());
|
||||
devices = deviceList.getData();
|
||||
devices = deviceList.getList();
|
||||
}
|
||||
|
||||
JSONArray deviceJSONList = new JSONArray();
|
||||
@@ -86,8 +81,8 @@ public class ApiDeviceController {
|
||||
deviceJsonObject.put("Online", device.getOnline() == 1);
|
||||
deviceJsonObject.put("Password", "");
|
||||
deviceJsonObject.put("MediaTransport", device.getTransport());
|
||||
deviceJsonObject.put("RemoteIP", device.getHost().getIp());
|
||||
deviceJsonObject.put("RemotePort", device.getHost().getPort());
|
||||
deviceJsonObject.put("RemoteIP", device.getIp());
|
||||
deviceJsonObject.put("RemotePort", device.getPort());
|
||||
deviceJsonObject.put("LastRegisterAt", "");
|
||||
deviceJsonObject.put("LastKeepaliveAt", "");
|
||||
deviceJsonObject.put("UpdatedAt", "");
|
||||
@@ -123,9 +118,9 @@ public class ApiDeviceController {
|
||||
deviceChannels = storager.queryChannelsByDeviceId(serial);
|
||||
result.put("ChannelCount", deviceChannels.size());
|
||||
}else {
|
||||
PageResult<DeviceChannel> pageResult = storager.queryChannelsByDeviceId(serial, null, null, null,start/limit, limit);
|
||||
PageInfo<DeviceChannel> pageResult = storager.queryChannelsByDeviceId(serial, null, null, null,start/limit, limit);
|
||||
result.put("ChannelCount", pageResult.getTotal());
|
||||
deviceChannels = pageResult.getData();
|
||||
deviceChannels = pageResult.getList();
|
||||
}
|
||||
|
||||
JSONArray channleJSONList = new JSONArray();
|
||||
@@ -159,7 +154,7 @@ public class ApiDeviceController {
|
||||
deviceJOSNChannel.put("PTZType ", deviceChannel.getPTZType()); // 云台类型, 0 - 未知, 1 - 球机, 2 - 半球,
|
||||
// 3 - 固定枪机, 4 - 遥控枪机
|
||||
deviceJOSNChannel.put("CustomPTZType", "");
|
||||
deviceJOSNChannel.put("StreamID", deviceChannel.getSsrc()); // StreamID 直播流ID, 有值表示正在直播
|
||||
deviceJOSNChannel.put("StreamID", deviceChannel.getStreamId()); // StreamID 直播流ID, 有值表示正在直播
|
||||
deviceJOSNChannel.put("NumOutputs ", -1); // 直播在线人数
|
||||
channleJSONList.add(deviceJOSNChannel);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||
import com.genersoft.iot.vmp.vmanager.play.PlayController;
|
||||
import org.slf4j.Logger;
|
||||
@@ -17,6 +18,7 @@ import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
|
||||
/**
|
||||
* 兼容LiveGBS的API:实时直播
|
||||
@@ -34,12 +36,17 @@ public class ApiStreamController {
|
||||
@Autowired
|
||||
private IVideoManagerStorager storager;
|
||||
|
||||
private boolean closeWaitRTPInfo = false;
|
||||
@Autowired
|
||||
private IRedisCatchStorage redisCatchStorage;
|
||||
|
||||
|
||||
@Autowired
|
||||
private ZLMRESTfulUtils zlmresTfulUtils;
|
||||
|
||||
|
||||
@Autowired
|
||||
private PlayController playController;
|
||||
|
||||
/**
|
||||
* 实时直播 - 开始直播
|
||||
* @param serial 设备编号
|
||||
@@ -54,126 +61,54 @@ public class ApiStreamController {
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/start")
|
||||
private JSONObject start(String serial ,
|
||||
@RequestParam(required = false)Integer channel ,
|
||||
@RequestParam(required = false)String code,
|
||||
@RequestParam(required = false)String cdn,
|
||||
@RequestParam(required = false)String audio,
|
||||
@RequestParam(required = false)String transport,
|
||||
@RequestParam(required = false)String checkchannelstatus ,
|
||||
@RequestParam(required = false)String transportmode,
|
||||
@RequestParam(required = false)String timeout
|
||||
private DeferredResult<JSONObject> start(String serial ,
|
||||
@RequestParam(required = false)Integer channel ,
|
||||
@RequestParam(required = false)String code,
|
||||
@RequestParam(required = false)String cdn,
|
||||
@RequestParam(required = false)String audio,
|
||||
@RequestParam(required = false)String transport,
|
||||
@RequestParam(required = false)String checkchannelstatus ,
|
||||
@RequestParam(required = false)String transportmode,
|
||||
@RequestParam(required = false)String timeout
|
||||
|
||||
){
|
||||
int getEncoding = closeWaitRTPInfo? 1: 0;
|
||||
DeferredResult<JSONObject> resultDeferredResult = new DeferredResult<JSONObject>();
|
||||
Device device = storager.queryVideoDevice(serial);
|
||||
|
||||
if (device == null ) {
|
||||
JSONObject result = new JSONObject();
|
||||
result.put("error","device[ " + serial + " ]未找到");
|
||||
return result;
|
||||
resultDeferredResult.setResult(result);
|
||||
}else if (device.getOnline() == 0) {
|
||||
JSONObject result = new JSONObject();
|
||||
result.put("error","device[ " + code + " ]offline");
|
||||
return result;
|
||||
resultDeferredResult.setResult(result);
|
||||
}
|
||||
resultDeferredResult.onTimeout(()->{
|
||||
logger.info("播放等待超时");
|
||||
JSONObject result = new JSONObject();
|
||||
result.put("error","timeout");
|
||||
resultDeferredResult.setResult(result);
|
||||
|
||||
// 清理RTP server
|
||||
});
|
||||
|
||||
DeviceChannel deviceChannel = storager.queryChannel(serial, code);
|
||||
if (deviceChannel == null) {
|
||||
JSONObject result = new JSONObject();
|
||||
result.put("error","channel[ " + code + " ]未找到");
|
||||
return result;
|
||||
resultDeferredResult.setResult(result);
|
||||
}else if (deviceChannel.getStatus() == 0) {
|
||||
JSONObject result = new JSONObject();
|
||||
result.put("error","channel[ " + code + " ]offline");
|
||||
return result;
|
||||
resultDeferredResult.setResult(result);
|
||||
}
|
||||
DeferredResult<ResponseEntity<String>> play = playController.play(serial, code);
|
||||
|
||||
// 查询是否已经在播放
|
||||
StreamInfo streamInfo = storager.queryPlayByDevice(device.getDeviceId(), code);
|
||||
if (streamInfo == null) {
|
||||
logger.debug("streamInfo 等于null, 重新点播");
|
||||
// streamInfo = cmder.playStreamCmd(device, code);
|
||||
}else {
|
||||
logger.debug("streamInfo 不等于null, 向流媒体查询是否正在推流");
|
||||
String streamId = String.format("%08x", Integer.parseInt(streamInfo.getSsrc())).toUpperCase();
|
||||
JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId);
|
||||
if (rtpInfo.getBoolean("exist")) {
|
||||
logger.debug("向流媒体查询正在推流, 直接返回: " + streamInfo.getRtsp());
|
||||
JSONObject result = new JSONObject();
|
||||
result.put("StreamID", streamInfo.getSsrc());
|
||||
result.put("DeviceID", device.getDeviceId());
|
||||
result.put("ChannelID", code);
|
||||
result.put("ChannelName", deviceChannel.getName());
|
||||
result.put("ChannelCustomName", "");
|
||||
result.put("FLV", streamInfo.getFlv());
|
||||
result.put("WS_FLV", streamInfo.getWs_flv());
|
||||
result.put("RTMP", streamInfo.getRtmp());
|
||||
result.put("HLS", streamInfo.getHls());
|
||||
result.put("RTSP", streamInfo.getRtsp());
|
||||
result.put("CDN", "");
|
||||
result.put("SnapURL", "");
|
||||
result.put("Transport", device.getTransport());
|
||||
result.put("StartAt", "");
|
||||
result.put("Duration", "");
|
||||
result.put("SourceVideoCodecName", "");
|
||||
result.put("SourceVideoWidth", "");
|
||||
result.put("SourceVideoHeight", "");
|
||||
result.put("SourceVideoFrameRate", "");
|
||||
result.put("SourceAudioCodecName", "");
|
||||
result.put("SourceAudioSampleRate", "");
|
||||
result.put("AudioEnable", "");
|
||||
result.put("Ondemand", "");
|
||||
result.put("InBytes", "");
|
||||
result.put("InBitRate", "");
|
||||
result.put("OutBytes", "");
|
||||
result.put("NumOutputs", "");
|
||||
result.put("CascadeSize", "");
|
||||
result.put("RelaySize", "");
|
||||
result.put("ChannelPTZType", 0);
|
||||
return result;
|
||||
} else {
|
||||
logger.debug("向流媒体查询没有推流, 重新点播");
|
||||
storager.stopPlay(streamInfo);
|
||||
// streamInfo = cmder.playStreamCmd(device, code);
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("设备预览 API调用,deviceId:%s ,channelId:%s",serial, code));
|
||||
logger.debug("设备预览 API调用,ssrc:"+streamInfo.getSsrc()+",ZLMedia streamId:"+Integer.toHexString(Integer.parseInt(streamInfo.getSsrc())));
|
||||
}
|
||||
boolean lockFlag = true;
|
||||
long startTime = System.currentTimeMillis();
|
||||
while (lockFlag) {
|
||||
try {
|
||||
if (System.currentTimeMillis() - startTime > 10 * 1000) {
|
||||
storager.stopPlay(streamInfo);
|
||||
logger.info("播放等待超时");
|
||||
JSONObject result = new JSONObject();
|
||||
result.put("error","timeout");
|
||||
return result;
|
||||
} else {
|
||||
|
||||
StreamInfo streamInfoNow = storager.queryPlayByDevice(serial, code);
|
||||
logger.debug("正在向流媒体查询");
|
||||
if (streamInfoNow != null && streamInfoNow.getFlv() != null) {
|
||||
streamInfo = streamInfoNow;
|
||||
logger.debug("向流媒体查询到: " + streamInfoNow.getRtsp());
|
||||
lockFlag = false;
|
||||
continue;
|
||||
} else {
|
||||
Thread.sleep(2000);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if(streamInfo!=null) {
|
||||
play.setResultHandler((Object o)->{
|
||||
ResponseEntity<String> responseEntity = (ResponseEntity)o;
|
||||
StreamInfo streamInfo = JSON.parseObject(responseEntity.getBody(), StreamInfo.class);
|
||||
JSONObject result = new JSONObject();
|
||||
result.put("StreamID", streamInfo.getSsrc());
|
||||
result.put("StreamID", streamInfo.getStreamId());
|
||||
result.put("DeviceID", device.getDeviceId());
|
||||
result.put("ChannelID", code);
|
||||
result.put("ChannelName", deviceChannel.getName());
|
||||
@@ -203,13 +138,9 @@ public class ApiStreamController {
|
||||
result.put("CascadeSize", "");
|
||||
result.put("RelaySize", "");
|
||||
result.put("ChannelPTZType", 0);
|
||||
return result;
|
||||
} else {
|
||||
logger.warn("设备预览API调用失败!");
|
||||
JSONObject result = new JSONObject();
|
||||
result.put("error","调用失败");
|
||||
return result;
|
||||
}
|
||||
resultDeferredResult.setResult(result);
|
||||
});
|
||||
return resultDeferredResult;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -228,14 +159,15 @@ public class ApiStreamController {
|
||||
@RequestParam(required = false)String check_outputs
|
||||
|
||||
){
|
||||
StreamInfo streamInfo = storager.queryPlayByDevice(serial, code);
|
||||
|
||||
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(serial, code);
|
||||
if (streamInfo == null) {
|
||||
JSONObject result = new JSONObject();
|
||||
result.put("error","未找到流信息");
|
||||
return result;
|
||||
}
|
||||
cmder.streamByeCmd(streamInfo.getSsrc());
|
||||
storager.stopPlay(streamInfo);
|
||||
cmder.streamByeCmd(streamInfo.getStreamId());
|
||||
redisCatchStorage.stopPlay(streamInfo);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user