Browse Source

离在线状态样式修改

修复未回复200ok导致catalog一直发送的bug
修改点播接口未收到视频后回复
pull/1/head
648540858 4 years ago
parent
commit
d4ae8194eb
  1. 58
      src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
  2. 17
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
  3. 5
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
  4. 36
      src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
  5. 16
      src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java
  6. 24
      src/main/java/com/genersoft/iot/vmp/storager/jdbc/VideoManagerJdbcStoragerImpl.java
  7. 42
      src/main/java/com/genersoft/iot/vmp/storager/redis/VideoManagerRedisStoragerImpl.java
  8. 16
      src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java
  9. 15
      src/main/java/com/genersoft/iot/vmp/web/ApiStreamController.java
  10. 23
      web_src/src/components/channelList.vue
  11. 1
      web_src/src/components/gb28181/devicePlayer.vue
  12. 6
      web_src/src/components/videoList.vue

58
src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java

@ -3,11 +3,13 @@ package com.genersoft.iot.vmp.common;
public class StreamInfo {
private String ssrc;
private String deviceID;
private String cahnnelId;
private String flv;
private String WS_FLV;
private String RTMP;
private String HLS;
private String RTSP;
private String ws_flv;
private String rtmp;
private String hls;
private String rtsp;
public String getSsrc() {
return ssrc;
@ -25,35 +27,51 @@ public class StreamInfo {
this.flv = flv;
}
public String getWS_FLV() {
return WS_FLV;
public String getWs_flv() {
return ws_flv;
}
public void setWS_FLV(String WS_FLV) {
this.WS_FLV = WS_FLV;
public void setWs_flv(String ws_flv) {
this.ws_flv = ws_flv;
}
public String getRTMP() {
return RTMP;
public String getRtmp() {
return rtmp;
}
public void setRTMP(String RTMP) {
this.RTMP = RTMP;
public void setRtmp(String rtmp) {
this.rtmp = rtmp;
}
public String getHLS() {
return HLS;
public String getHls() {
return hls;
}
public void setHLS(String HLS) {
this.HLS = HLS;
public void setHls(String hls) {
this.hls = hls;
}
public String getRTSP() {
return RTSP;
public String getRtsp() {
return rtsp;
}
public void setRTSP(String RTSP) {
this.RTSP = RTSP;
public void setRtsp(String rtsp) {
this.rtsp = rtsp;
}
public String getDeviceID() {
return deviceID;
}
public void setDeviceID(String deviceID) {
this.deviceID = deviceID;
}
public String getCahnnelId() {
return cahnnelId;
}
public void setCahnnelId(String cahnnelId) {
this.cahnnelId = cahnnelId;
}
}

17
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java

@ -242,14 +242,15 @@ public class SIPCommander implements ISIPCommander {
StreamInfo streamInfo = new StreamInfo();
streamInfo.setSsrc(ssrc);
// String streamId = Integer.toHexString(Integer.parseInt(streamInfo.getSsrc()));
String streamId = String.format("%08x", Integer.parseInt(streamInfo.getSsrc())).toUpperCase(); // ZLM 要求大写且首位补零
streamInfo.setFlv(String.format("http://%s:%s/rtp/%s.flv", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId));
streamInfo.setWS_FLV(String.format("ws://%s:%s/rtp/%s.flv", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId));
streamInfo.setRTMP(String.format("rtmp://%s:%s/rtp/%s", mediaInfo.getLocalIP(), mediaInfo.getRtmpPort(), streamId));
streamInfo.setHLS(String.format("http://%s:%s/rtp/%s/hls.m3u8", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId));
streamInfo.setRTSP(String.format("rtsp://%s:%s/rtp/%s", mediaInfo.getLocalIP(), mediaInfo.getRtspPort(), streamId));
storager.startPlay(device.getDeviceId(), channelId, streamInfo);
// String streamId = String.format("%08x", Integer.parseInt(streamInfo.getSsrc())).toUpperCase(); // ZLM 要求大写且首位补零
// streamInfo.setFlv(String.format("http://%s:%s/rtp/%s.flv", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId));
// streamInfo.setWS_FLV(String.format("ws://%s:%s/rtp/%s.flv", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId));
// streamInfo.setRTMP(String.format("rtmp://%s:%s/rtp/%s", mediaInfo.getLocalIP(), mediaInfo.getRtmpPort(), streamId));
// streamInfo.setHLS(String.format("http://%s:%s/rtp/%s/hls.m3u8", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId));
// streamInfo.setRTSP(String.format("rtsp://%s:%s/rtp/%s", mediaInfo.getLocalIP(), mediaInfo.getRtspPort(), streamId));
streamInfo.setCahnnelId(channelId);
streamInfo.setDeviceID(device.getDeviceId());
storager.startPlay(streamInfo);
return streamInfo;
} catch ( SipException | ParseException | InvalidArgumentException e) {
e.printStackTrace();

5
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java

@ -210,8 +210,11 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
msg.setType(DeferredResultHolder.CALLBACK_CMD_CATALOG);
msg.setData(device);
deferredResultHolder.invokeResult(msg);
// 回复200
responseAck(evt);
}
} catch (DocumentException e) {
} catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
e.printStackTrace();
}
}

36
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java

@ -1,11 +1,13 @@
package com.genersoft.iot.vmp.media.zlm;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.MediaServerConfig;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
import com.genersoft.iot.vmp.utils.IpUtil;
@ -35,7 +37,8 @@ import javax.servlet.http.HttpServletRequest;
public class ZLMHttpHookListener {
private final static Logger logger = LoggerFactory.getLogger(ZLMHttpHookListener.class);
@Autowired
private SIPCommander cmder;
@ -54,7 +57,7 @@ public class ZLMHttpHookListener {
logger.debug("ZLM HOOK on_flow_report API调用,参数:" + json.toString());
}
// TODO Auto-generated method stub
JSONObject ret = new JSONObject();
ret.put("code", 0);
@ -113,6 +116,21 @@ public class ZLMHttpHookListener {
if (logger.isDebugEnabled()) {
logger.debug("ZLM HOOK on_publish API调用,参数:" + json.toString());
}
String app = json.getString("app");
String streamId = json.getString("id");
// String ssrc = String.format("%10d", Integer.parseInt(streamId, 16)); // ZLM 要求大写且首位补零
String ssrc = new DecimalFormat("0000000000").format(Integer.parseInt(streamId, 16));
StreamInfo streamInfo = storager.queryPlayBySSRC(ssrc);
if ("rtp".equals(app) && streamInfo != null ) {
MediaServerConfig mediaInfo = storager.getMediaInfo();
streamInfo.setFlv(String.format("http://%s:%s/rtp/%s.flv", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId));
streamInfo.setWs_flv(String.format("ws://%s:%s/rtp/%s.flv", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId));
streamInfo.setRtmp(String.format("rtmp://%s:%s/rtp/%s", mediaInfo.getLocalIP(), mediaInfo.getRtmpPort(), streamId));
streamInfo.setHls(String.format("http://%s:%s/rtp/%s/hls.m3u8", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId));
streamInfo.setRtsp(String.format("rtsp://%s:%s/rtp/%s", mediaInfo.getLocalIP(), mediaInfo.getRtspPort(), streamId));
storager.startPlay(streamInfo);
}
// TODO Auto-generated method stub
JSONObject ret = new JSONObject();
@ -213,8 +231,18 @@ public class ZLMHttpHookListener {
if (logger.isDebugEnabled()) {
logger.debug("ZLM HOOK on_stream_changed API调用,参数:" + json.toString());
}
// TODO Auto-generated method stub
// 流消失移除redis play
String app = json.getString("app");
String streamId = json.getString("stream");
boolean regist = json.getBoolean("regist");
// String ssrc = String.format("%10d", Integer.parseInt(streamId, 16)); // ZLM 要求大写且首位补零
String ssrc = new DecimalFormat("0000000000").format(Integer.parseInt(streamId, 16));
StreamInfo streamInfo = storager.queryPlayBySSRC(ssrc);
if ("rtp".equals(app) && !regist ) {
storager.stopPlay(streamInfo);
}
JSONObject ret = new JSONObject();
ret.put("code", 0);
ret.put("msg", "success");

16
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java

@ -136,30 +136,24 @@ public interface IVideoManagerStorager {
/**
* 开始播放时将流存入
*
* @param deviceId 设备ID
* @param channelId 通道ID
* @param stream 流信息
* @return
*/
public boolean startPlay(String deviceId, String channelId, StreamInfo stream);
public boolean startPlay(StreamInfo stream);
/**
* 停止播放时删除
*
* @param deviceId 设备ID
* @param channelId 通道ID
* @return
*/
public boolean stopPlay(String deviceId, String channelId);
public boolean stopPlay(StreamInfo streamInfo);
/**
* 查找视频流
*
* @param deviceId 设备ID
* @param channelId 通道ID
* @return
*/
public StreamInfo queryPlay(String deviceId, String channelId);
public StreamInfo queryPlay(StreamInfo streamInfo);
/**
* 查询子设备
@ -182,4 +176,8 @@ public interface IVideoManagerStorager {
* @param deviceId
*/
void cleanChannelsForDevice(String deviceId);
StreamInfo queryPlayBySSRC(String ssrc);
StreamInfo queryPlayByDevice(String deviceId, String code);
}

24
src/main/java/com/genersoft/iot/vmp/storager/jdbc/VideoManagerJdbcStoragerImpl.java

@ -148,17 +148,12 @@ public class VideoManagerJdbcStoragerImpl implements IVideoManagerStorager {
}
@Override
public boolean startPlay(String deviceId, String channelId, StreamInfo stream) {
public boolean stopPlay(StreamInfo streamInfo) {
return false;
}
@Override
public boolean stopPlay(String deviceId, String channelId) {
return false;
}
@Override
public StreamInfo queryPlay(String deviceId, String channelId) {
public StreamInfo queryPlay(StreamInfo streamInfo) {
return null;
}
@ -176,4 +171,19 @@ public class VideoManagerJdbcStoragerImpl implements IVideoManagerStorager {
public void cleanChannelsForDevice(String deviceId) {
}
@Override
public boolean startPlay(StreamInfo stream) {
return false;
}
@Override
public StreamInfo queryPlayBySSRC(String ssrc) {
return null;
}
@Override
public StreamInfo queryPlayByDevice(String deviceId, String code) {
return null;
}
}

42
src/main/java/com/genersoft/iot/vmp/storager/redis/VideoManagerRedisStoragerImpl.java

@ -329,40 +329,53 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager {
/**
* 开始播放时将流存入redis
*
* @param deviceId 设备ID
* @param channelId 通道ID
* @return
*/
@Override
public boolean startPlay(String deviceId, String channelId, StreamInfo stream) {
return redis.set(String.format("%S_%s_%s", VideoManagerConstants.PLAYER_PREFIX, deviceId, channelId),
public boolean startPlay(StreamInfo stream) {
return redis.set(String.format("%S_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX, stream.getSsrc(),stream.getDeviceID(), stream.getCahnnelId()),
stream);
}
/**
* 停止播放时从redis删除
*
* @param deviceId 设备ID
* @param channelId 通道ID
* @return
*/
@Override
public boolean stopPlay(String deviceId, String channelId) {
return redis.del(String.format("%S_%s_%s", VideoManagerConstants.PLAYER_PREFIX, deviceId, channelId));
public boolean stopPlay(StreamInfo streamInfo) {
return redis.del(String.format("%S_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX,
streamInfo.getSsrc(),
streamInfo.getDeviceID(),
streamInfo.getCahnnelId()));
}
/**
* 查询播放列表
* @param deviceId 设备ID
* @param channelId 通道ID
* @return
*/
@Override
public StreamInfo queryPlay(String deviceId, String channelId) {
return (StreamInfo)redis.get(String.format("%S_%s_%s", VideoManagerConstants.PLAYER_PREFIX, deviceId, channelId));
public StreamInfo queryPlay(StreamInfo streamInfo) {
return (StreamInfo)redis.get(String.format("%S_%s_%s_%s",
VideoManagerConstants.PLAYER_PREFIX,
streamInfo.getSsrc(),
streamInfo.getDeviceID(),
streamInfo.getCahnnelId()));
}
@Override
public StreamInfo queryPlayBySSRC(String ssrc) {
List<Object> playLeys = redis.keys(String.format("%S_%s_*", VideoManagerConstants.PLAYER_PREFIX, ssrc));
if (playLeys.size() == 0) return null;
return (StreamInfo)redis.get(playLeys.get(0).toString());
}
@Override
public StreamInfo queryPlayByDevice(String deviceId, String code) {
List<Object> playLeys = redis.keys(String.format("%S_*_%s_%s", VideoManagerConstants.PLAYER_PREFIX,
deviceId,
code));
return (StreamInfo)redis.get(playLeys.get(0).toString());
}
/**
* 更新流媒体信息
@ -423,4 +436,7 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager {
}
}
}
}

16
src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java

@ -37,7 +37,18 @@ public class PlayController {
Device device = storager.queryVideoDevice(deviceId);
StreamInfo streamInfo = cmder.playStreamCmd(device, channelId);
// 等待推流, TODO 默认超时15s
long startTime = System.currentTimeMillis();
while (storager.queryPlay(streamInfo) == null || storager.queryPlay(streamInfo).getFlv() == null) {
try {
if (System.currentTimeMillis() - startTime > 15 * 1000)
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
streamInfo = storager.queryPlay(streamInfo);
if (logger.isDebugEnabled()) {
logger.debug(String.format("设备预览 API调用,deviceId:%s ,channelId:%s",deviceId, channelId));
logger.debug("设备预览 API调用,ssrc:"+streamInfo.getSsrc()+",ZLMedia streamId:"+Integer.toHexString(Integer.parseInt(streamInfo.getSsrc())));
@ -55,7 +66,8 @@ public class PlayController {
public ResponseEntity<String> playStop(@PathVariable String ssrc){
cmder.streamByeCmd(ssrc);
StreamInfo streamInfo = storager.queryPlayBySSRC(ssrc);
storager.stopPlay(streamInfo);
if (logger.isDebugEnabled()) {
logger.debug(String.format("设备预览停止API调用,ssrc:%s", ssrc));
}

15
src/main/java/com/genersoft/iot/vmp/web/ApiStreamController.java

@ -70,7 +70,7 @@ public class ApiStreamController {
return result;
}
// 查询是否已经在播放
StreamInfo streamInfo = storager.queryPlay(device.getDeviceId(), code);
StreamInfo streamInfo = storager.queryPlayByDevice(device.getDeviceId(), code);
if (streamInfo == null) streamInfo = cmder.playStreamCmd(device, code);
if (logger.isDebugEnabled()) {
@ -86,10 +86,10 @@ public class ApiStreamController {
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("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());
@ -135,14 +135,14 @@ public class ApiStreamController {
@RequestParam(required = false)String check_outputs
){
StreamInfo streamInfo = storager.queryPlay(serial, code);
StreamInfo streamInfo = storager.queryPlayByDevice(serial, code);
if (streamInfo == null) {
JSONObject result = new JSONObject();
result.put("error","未找到流信息");
return result;
}
cmder.streamByeCmd(streamInfo.getSsrc());
storager.stopPlay(serial, code);
storager.stopPlay(streamInfo);
return null;
}
@ -151,7 +151,6 @@ public class ApiStreamController {
* @param serial 设备编号
* @param channel 通道序号
* @param code 通道国标编号
* @param check_outputs
* @return
*/
@RequestMapping(value = "/touch")

23
web_src/src/components/channelList.vue

@ -35,8 +35,16 @@
</el-table-column>
<el-table-column prop="subCount" label="子节点数">
</el-table-column>
<el-table-column prop="ptztypeText" label="云台类型">
</el-table-column>
<el-table-column label="状态" width="180" align="center">
<template slot-scope="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium" v-if="scope.row.status == 1">在线</el-tag>
<el-tag size="medium" type="info" v-if="scope.row.status == 0">离线</el-tag>
</div>
</template>
</el-table-column>
<el-table-column prop="ptztypeText" label="云台类型">
</el-table-column>
<el-table-column label="操作" width="240" align="center" fixed="right">
<template slot-scope="scope">
<el-button size="mini" icon="el-icon-video-play" v-if="scope.row.parental == 0" @click="sendDevicePush(scope.row)">预览视频</el-button>
@ -58,17 +66,20 @@
</el-main>
</el-container>
<Loading v-if="isLoging" marginTop="-50%"></Loading>
</div>
</template>
<script>
import devicePlayer from './gb28181/devicePlayer.vue'
import uiHeader from './UiHeader.vue'
import Loading from './Loading.vue'
export default {
name: 'channelList',
components: {
devicePlayer,
uiHeader
uiHeader,
Loading
},
data() {
return {
@ -85,7 +96,8 @@
currentPage: parseInt(this.$route.params.page),
count: parseInt(this.$route.params.count),
total:0,
beforeUrl:"/videoList"
beforeUrl:"/videoList",
isLoging: false
};
},
@ -182,7 +194,7 @@
//
sendDevicePush: function(itemData) {
let deviceId = this.deviceId;
this.isLoging = true;
let channelId = itemData.channelId;
console.log("通知设备推流1:" + deviceId + " : " + channelId);
let that = this;
@ -191,6 +203,7 @@
url: '/api/play/' + deviceId + '/' + channelId
}).then(function(res) {
let ssrc = res.data.ssrc;
that.isLoging = false
that.$refs.devicePlayer.play(res.data,deviceId,channelId);
}).catch(function(e) {
});

1
web_src/src/components/gb28181/devicePlayer.vue

@ -115,6 +115,7 @@
deviceId: '',
channelId: '',
tabActiveName: 'media'
};
},
methods: {

6
web_src/src/components/videoList.vue

@ -1,7 +1,6 @@
<template>
<div id="app">
<el-container>
<el-header>
<uiHeader></uiHeader>
</el-header>
@ -37,14 +36,15 @@
<el-table-column label="状态" width="180" align="center">
<template slot-scope="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium">{{ scope.row.online==1?'在线' :'离线'}}</el-tag>
<el-tag size="medium" v-if="scope.row.online == 1">在线</el-tag>
<el-tag size="medium" type="info" v-if="scope.row.online == 0">离线</el-tag>
</div>
</template>
</el-table-column>
<el-table-column label="操作" width="240" align="center" fixed="right">
<template slot-scope="scope">
<el-button size="mini" icon="el-icon-refresh" @click="refDevice(scope.row)">刷新</el-button>
<el-button size="mini" icon="el-icon-refresh" @click="refDevice(scope.row)">刷新通道</el-button>
<el-button size="mini" icon="el-icon-s-open" type="primary" @click="showChannelList(scope.row)">查看通道</el-button>
</template>
</el-table-column>

Loading…
Cancel
Save