648540858
2021-11-26 54568adfdd460164eba5c703f15b2d68b7971cd4
优化录像下载逻辑以及录像查询逻辑
16个文件已修改
131 ■■■■ 已修改文件
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 15 ●●●●● 补丁 | 查看 | 原始文档 | 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 | 历史
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
@@ -358,14 +358,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 +377,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 +391,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);
        }));