648540858
2021-11-29 019827fd35f84465ee503fcc248b12a045da44d2
Merge remote-tracking branch 'origin/wvp-28181-2.0' into wvp-28181-2.0
16个文件已修改
2个文件已添加
180 ■■■■ 已修改文件
.github/ISSUE_TEMPLATE/-------.md 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.github/ISSUE_TEMPLATE/--bug---.md 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/CheckForAllRecordsThread.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/MessageRequestProcessor1.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java 25 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/IPlayService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.github/ISSUE_TEMPLATE/-------.md
New file
@@ -0,0 +1,10 @@
---
name: "[ 新功能 ]"
about: 新功能
title: ''
labels: ''
assignees: ''
---
.github/ISSUE_TEMPLATE/--bug---.md
New file
@@ -0,0 +1,29 @@
---
name: "[ BUG ] "
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**描述错误**
描述下您遇到的问题
**如何复现**
有明确复现步骤的问题会很容易被解决
**预期行为**
清晰简洁的描述您期望发生的事情
**截图**
**环境信息:**
 - 1. 部署方式 wvp-pro docker / zlm(docker) + 编译wvp-pro/ wvp-prp + zlm都是编译部署/
 - 2. 部署环境 windows / ubuntu/ centos ...
 - 3. 端口开放情况
 - 4. 是否是公网部署
 - 5. 是否使用https
 - 6. 方便的话提供下使用的设备品牌或平台
 - 7. 你做过哪些尝试
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
@@ -27,6 +27,7 @@
    public static final String PLAYER_PREFIX = "VMP_PLAYER_";
    public static final String PLAY_BLACK_PREFIX = "VMP_PLAYBACK_";
    public static final String DOWNLOAD_PREFIX = "VMP_DOWNLOAD_";
    public static final String PLATFORM_KEEPLIVEKEY_PREFIX = "VMP_PLATFORM_KEEPLIVE_";
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java
@@ -16,6 +16,8 @@
    private String channelId;
    private String sn;
    private String name;
    
    private int sumNum;
@@ -61,4 +63,12 @@
    public void setChannelId(String channelId) {
        this.channelId = channelId;
    }
    public String getSn() {
        return sn;
    }
    public void setSn(String sn) {
        this.sn = sn;
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/CheckForAllRecordsThread.java
@@ -53,7 +53,7 @@
        // 自然顺序排序, 元素进行升序排列
        this.recordInfo.getRecordList().sort(Comparator.naturalOrder());
        RequestMessage msg = new RequestMessage();
        msg.setKey(DeferredResultHolder.CALLBACK_CMD_RECORDINFO + recordInfo.getDeviceId() + recordInfo.getChannelId());
        msg.setKey(DeferredResultHolder.CALLBACK_CMD_RECORDINFO + recordInfo.getDeviceId() + recordInfo.getSn());
        msg.setData(recordInfo);
        deferredResultHolder.invokeAllResult(msg);
        logger.info("处理完成,返回结果");
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java
@@ -35,6 +35,10 @@
    public static final String CALLBACK_CMD_PLAY = "CALLBACK_PLAY";
    public static final String CALLBACK_CMD_PLAYBACK = "CALLBACK_PLAY";
    public static final String CALLBACK_CMD_DOWNLOAD = "CALLBACK_DOWNLOAD";
    public static final String CALLBACK_CMD_STOP = "CALLBACK_STOP";
    public static final String CALLBACK_CMD_MOBILEPOSITION = "CALLBACK_MOBILEPOSITION";
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
@@ -256,8 +256,9 @@
     * @param device 视频设备
     * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
     * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
     * @param sn
     */
    boolean recordInfoQuery(Device device, String channelId, String startTime, String endTime, SipSubscribe.Event errorEvent);
    boolean recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, SipSubscribe.Event errorEvent);
    
    /**
     * 查询报警信息
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -1196,14 +1196,15 @@
     * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
     */  
    @Override
    public boolean recordInfoQuery(Device device, String channelId, String startTime, String endTime, SipSubscribe.Event errorEvent) {
    public boolean recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, SipSubscribe.Event errorEvent) {
        try {
            StringBuffer recordInfoXml = new StringBuffer(200);
            recordInfoXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
            recordInfoXml.append("<Query>\r\n");
            recordInfoXml.append("<CmdType>RecordInfo</CmdType>\r\n");
            recordInfoXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
            recordInfoXml.append("<SN>" + sn + "</SN>\r\n");
            recordInfoXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
            recordInfoXml.append("<StartTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(startTime) + "</StartTime>\r\n");
            recordInfoXml.append("<EndTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(endTime) + "</EndTime>\r\n");
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/MessageRequestProcessor1.java
@@ -914,21 +914,20 @@
            String uuid = UUID.randomUUID().toString().replace("-", "");
            RecordInfo recordInfo = new RecordInfo();
            Element rootElement = getRootElement(evt);
            Element deviceIdElement = rootElement.element("DeviceID");
            String channelId = deviceIdElement.getText().toString();
            String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + channelId;
            String sn = getText(rootElement, "SN");
            String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + sn;
            if (device != null ) {
                rootElement = getRootElement(evt, device.getCharset());
            }
            recordInfo.setDeviceId(deviceId);
            recordInfo.setChannelId(channelId);
            recordInfo.setSn(sn);
            recordInfo.setName(getText(rootElement, "Name"));
            if (getText(rootElement, "SumNum")== null || getText(rootElement, "SumNum") =="") {
                recordInfo.setSumNum(0);
            } else {
                recordInfo.setSumNum(Integer.parseInt(getText(rootElement, "SumNum")));
            }
            String sn = getText(rootElement, "SN");
            Element recordListElement = rootElement.element("RecordList");
            if (recordListElement == null || recordInfo.getSumNum() == 0) {
                logger.info("无录像数据");
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java
@@ -64,18 +64,16 @@
            rootElement = getRootElement(evt, device.getCharset());
            String uuid = UUID.randomUUID().toString().replace("-", "");
            RecordInfo recordInfo = new RecordInfo();
            Element deviceIdElement = rootElement.element("DeviceID");
            String channelId = deviceIdElement.getText();
            String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + device.getDeviceId() + channelId;
            String sn = getText(rootElement, "SN");
            String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + device.getDeviceId() + sn;
            recordInfo.setDeviceId(device.getDeviceId());
            recordInfo.setChannelId(channelId);
            recordInfo.setSn(sn);
            recordInfo.setName(getText(rootElement, "Name"));
            if (getText(rootElement, "SumNum") == null || getText(rootElement, "SumNum") == "") {
                recordInfo.setSumNum(0);
            } else {
                recordInfo.setSumNum(Integer.parseInt(getText(rootElement, "SumNum")));
            }
            String sn = getText(rootElement, "SN");
            Element recordListElement = rootElement.element("RecordList");
            if (recordListElement == null || recordInfo.getSumNum() == 0) {
                logger.info("无录像数据");
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -164,12 +164,20 @@
                subscribe.response(mediaInfo, json);
            }
        }
         String app = json.getString("app");
         String stream = json.getString("stream");
        StreamInfo streamInfo = redisCatchStorage.queryPlaybackByStreamId(stream);
        JSONObject ret = new JSONObject();
        // 录像回放时不进行录像下载
        if (streamInfo != null) {
            ret.put("enableMP4", false);
        }else {
            ret.put("enableMP4", userSetup.isRecordPushLive());
        }
        ret.put("code", 0);
        ret.put("msg", "success");
        ret.put("enableHls", true);
        ret.put("enableMP4", userSetup.isRecordPushLive());
        ret.put("enableRtxp", true);
        return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);
    }
    
@@ -358,14 +366,13 @@
        String mediaServerId = json.getString("mediaServerId");
        String streamId = json.getString("stream");
        String app = json.getString("app");
        // TODO 如果在给上级推流,也不停止。
        JSONObject ret = new JSONObject();
        ret.put("code", 0);
        if ("rtp".equals(app)){
            JSONObject ret = new JSONObject();
            ret.put("code", 0);
            ret.put("close", true);
            StreamInfo streamInfoForPlayCatch = redisCatchStorage.queryPlayByStreamId(streamId);
            if (streamInfoForPlayCatch != null) {
                // 如果在给上级推流,也不停止。
                if (redisCatchStorage.isChannelSendingRTP(streamInfoForPlayCatch.getChannelId())) {
                    ret.put("close", false);
                } else {
@@ -378,6 +385,12 @@
                if (streamInfoForPlayBackCatch != null) {
                    cmder.streamByeCmd(streamInfoForPlayBackCatch.getDeviceID(), streamInfoForPlayBackCatch.getChannelId());
                    redisCatchStorage.stopPlayback(streamInfoForPlayBackCatch);
                }else {
                    StreamInfo streamInfoForDownload = redisCatchStorage.queryDownloadByStreamId(streamId);
                    // 进行录像下载时无人观看不断流
                    if (streamInfoForDownload != null) {
                        ret.put("close", false);
                    }
                }
            }
            MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
@@ -386,8 +399,6 @@
            }
            return new ResponseEntity<String>(ret.toString(),HttpStatus.OK);
        }else {
            JSONObject ret = new JSONObject();
            ret.put("code", 0);
            StreamProxyItem streamProxyItem = streamProxyService.getStreamProxyByAppAndStream(app, streamId);
            if (streamProxyItem != null && streamProxyItem.isEnable_remove_none_reader()) {
                ret.put("close", true);
src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
@@ -18,4 +18,6 @@
    PlayResult play(MediaServerItem mediaServerItem, String deviceId, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
    MediaServerItem getNewMediaServerItem(Device device);
    void onPublishHandlerForDownload(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, String toString);
}
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -34,11 +34,6 @@
import org.springframework.util.ResourceUtils;
import org.springframework.web.context.request.async.DeferredResult;
import javax.sip.DialogTerminatedEvent;
import javax.sip.ResponseEvent;
import javax.sip.TimeoutEvent;
import javax.sip.TransactionTerminatedEvent;
import javax.sip.message.Response;
import java.io.FileNotFoundException;
import java.util.Objects;
import java.util.UUID;
@@ -286,14 +281,33 @@
        return mediaServerItem;
    }
    @Override
    public void onPublishHandlerForPlayBack(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) {
        RequestMessage msg = new RequestMessage();
        msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId);
        msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId);
        msg.setId(uuid);
        StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid);
        if (streamInfo != null) {
            redisCatchStorage.startPlayback(streamInfo);
            msg.setData(JSON.toJSONString(streamInfo));
            resultHolder.invokeResult(msg);
        } else {
            logger.warn("设备回放API调用失败!");
            msg.setData("设备回放API调用失败!");
            resultHolder.invokeResult(msg);
        }
    }
    @Override
    public void onPublishHandlerForDownload(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, String uuid) {
        RequestMessage msg = new RequestMessage();
        msg.setKey(DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId);
        msg.setId(uuid);
        StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId, uuid);
        if (streamInfo != null) {
            redisCatchStorage.startDownload(streamInfo);
            msg.setData(JSON.toJSONString(streamInfo));
            resultHolder.invokeResult(msg);
        } else {
@@ -303,6 +317,7 @@
        }
    }
    public StreamInfo onPublishHandler(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) {
        String streamId = resonse.getString("stream");
        JSONArray tracks = resonse.getJSONArray("tracks");
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
@@ -144,4 +144,12 @@
     * @param streamId
     */
    void removePushStream(MediaServerItem mediaServerItem, String app, String streamId);
    /**
     * 开始下载录像时存入
     * @param streamInfo
     */
    boolean startDownload(StreamInfo streamInfo);
    StreamInfo queryDownloadByStreamId(String streamId);
}
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
@@ -64,15 +64,15 @@
                streamInfo.getChannelId()));
    }
    @Override
    public StreamInfo queryPlayByStreamId(String steamId) {
        List<Object> playLeys = redis.scan(String.format("%S_%s_*", VideoManagerConstants.PLAYER_PREFIX, steamId));
    public StreamInfo queryPlayByStreamId(String streamId) {
        List<Object> playLeys = redis.scan(String.format("%S_%s_*", VideoManagerConstants.PLAYER_PREFIX, streamId));
        if (playLeys == null || playLeys.size() == 0) return null;
        return (StreamInfo)redis.get(playLeys.get(0).toString());
    }
    @Override
    public StreamInfo queryPlaybackByStreamId(String steamId) {
        List<Object> playLeys = redis.scan(String.format("%S_%s_*", VideoManagerConstants.PLAY_BLACK_PREFIX, steamId));
    public StreamInfo queryPlaybackByStreamId(String streamId) {
        List<Object> playLeys = redis.scan(String.format("%S_%s_*", VideoManagerConstants.PLAY_BLACK_PREFIX, streamId));
        if (playLeys == null || playLeys.size() == 0) return null;
        return (StreamInfo)redis.get(playLeys.get(0).toString());
    }
@@ -104,10 +104,15 @@
    @Override
    public boolean startPlayback(StreamInfo stream) {
        return redis.set(String.format("%S_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, stream.getStreamId(),stream.getDeviceID(), stream.getChannelId()),
                stream);
        return redis.set(String.format("%S_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, stream.getStreamId(),
                        stream.getDeviceID(), stream.getChannelId()), stream);
    }
    @Override
    public boolean startDownload(StreamInfo streamInfo) {
        return redis.set(String.format("%S_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX, streamInfo.getStreamId(),
                        streamInfo.getDeviceID(), streamInfo.getChannelId()), streamInfo);
    }
    @Override
    public boolean stopPlayback(StreamInfo streamInfo) {
@@ -318,4 +323,11 @@
        String key = VideoManagerConstants.WVP_SERVER_STREAM_PUSH_PREFIX + app + "_" + streamId + "_" + mediaServerItem.getId();
        redis.del(key);
    }
    @Override
    public StreamInfo queryDownloadByStreamId(String streamId) {
        List<Object> playLeys = redis.scan(String.format("%S_%s_*", VideoManagerConstants.DOWNLOAD_PREFIX, streamId));
        if (playLeys == null || playLeys.size() == 0) return null;
        return (StreamInfo)redis.get(playLeys.get(0).toString());
    }
}
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java
@@ -76,7 +76,7 @@
        if (logger.isDebugEnabled()) {
            logger.debug(String.format("历史媒体下载 API调用,deviceId:%s,channelId:%s,downloadSpeed:%s", deviceId, channelId, downloadSpeed));
        }
        String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId;
        String key = DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId;
        String uuid = UUID.randomUUID().toString();
        DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(30000L);
        // 超时处理
@@ -114,7 +114,7 @@
        cmder.downloadStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, (MediaServerItem mediaServerItem, JSONObject response) -> {
            logger.info("收到订阅消息: " + response.toJSONString());
            playService.onPublishHandlerForPlayBack(mediaServerItem, response, deviceId, channelId, uuid.toString());
            playService.onPublishHandlerForDownload(mediaServerItem, response, deviceId, channelId, uuid.toString());
        }, event -> {
            RequestMessage msg = new RequestMessage();
            msg.setId(uuid);
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java
@@ -78,7 +78,7 @@
            logger.debug(String.format("设备回放 API调用,deviceId:%s ,channelId:%s", deviceId, channelId));
        }
        String uuid = UUID.randomUUID().toString();
        String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId;
        String key = DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId;
        DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(30000L);
        Device device = storager.queryVideoDevice(deviceId);
        if (device == null) {
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java
@@ -59,11 +59,12 @@
        // 指定超时时间 1分钟30秒
        DeferredResult<ResponseEntity<RecordInfo>> result = new DeferredResult<>(90*1000L);
        String uuid = UUID.randomUUID().toString();
        String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + channelId;
        int sn  =  (int)((Math.random()*9+1)*100000);
        String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + sn;
        RequestMessage msg = new RequestMessage();
        msg.setId(uuid);
        msg.setKey(key);
        cmder.recordInfoQuery(device, channelId, startTime, endTime, (eventResult -> {
        cmder.recordInfoQuery(device, channelId, startTime, endTime, sn, (eventResult -> {
            msg.setData("查询录像失败, status: " +  eventResult.statusCode + ", message: " + eventResult.msg );
            resultHolder.invokeResult(msg);
        }));