648540858
2023-05-09 a2da81f79a40f275704e10789903ffe85d0c0be8
支持级联国标录像下载
8个文件已修改
66 ■■■■ 已修改文件
src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteStreamType.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web_src/src/components/GBRecordDetail.vue 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web_src/src/components/dialog/recordDownload.vue 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteStreamType.java
@@ -2,7 +2,7 @@
public enum InviteStreamType {
    PLAY,PLAYBACK,PUSH,PROXY,CLOUD_RECORD_PUSH,CLOUD_RECORD_PROXY
    PLAY,PLAYBACK,DOWNLOAD,PUSH,PROXY,CLOUD_RECORD_PUSH,CLOUD_RECORD_PROXY
}
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -540,7 +540,7 @@
        content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
        logger.debug("此时请求下载信令的ssrc===>{}",ssrcInfo.getSsrc());
        HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, null, mediaServerItem.getId());
        HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId());
        // 添加订阅
        CallIdHeader newCallIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()), device.getTransport());
        String callId= newCallIdHeader.getCallId();
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
@@ -429,8 +429,10 @@
                    InviteErrorCallback<Object> errorEvent = ((statusCode, msg, data) -> {
                        // 未知错误。直接转发设备点播的错误
                        try {
                            if (statusCode > 0) {
                            Response response = getMessageFactory().createResponse(statusCode, evt.getRequest());
                            sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
                            }
                        } catch (ParseException | SipException  e) {
                            logger.error("未处理的异常 ", e);
                        }
@@ -455,6 +457,36 @@
                                        errorEvent.run(code, msg, data);
                                    }
                                });
                    }else if ("Download".equalsIgnoreCase(sessionName)) {
                        // 获取指定的下载速度
                        Vector sdpMediaDescriptions = sdp.getMediaDescriptions(true);
                        MediaDescription mediaDescription = null;
                        String downloadSpeed = "1";
                        if (sdpMediaDescriptions.size() > 0) {
                            mediaDescription = (MediaDescription)sdpMediaDescriptions.get(0);
                        }
                        if (mediaDescription != null) {
                            downloadSpeed = mediaDescription.getAttribute("downloadspeed");
                        }
                        sendRtpItem.setPlayType(InviteStreamType.DOWNLOAD);
                        SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, null, device.isSsrcCheck(), true, 0, false, device.getStreamModeForParam());
                        sendRtpItem.setStreamId(ssrcInfo.getStream());
                        // 写入redis, 超时时回复
                        redisCatchStorage.updateSendRTPSever(sendRtpItem);
                        playService.download(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, DateUtil.formatter.format(start),
                                DateUtil.formatter.format(end), Integer.parseInt(downloadSpeed),
                                (code, msg, data) -> {
                                    if (code == InviteErrorCode.SUCCESS.getCode()){
                                        hookEvent.run(code, msg, data);
                                    }else if (code == InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode() || code == InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode()){
                                        logger.info("[录像下载]超时, 用户:{}, 通道:{}", username, channelId);
                                        redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null);
                                        errorEvent.run(code, msg, data);
                                    }else {
                                        errorEvent.run(code, msg, data);
                                    }
                                });
                    } else {
                        sendRtpItem.setPlayType(InviteStreamType.PLAY);
                        String streamId = null;
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -438,7 +438,7 @@
    @PostMapping(value = "/on_stream_none_reader", produces = "application/json;charset=UTF-8")
    public JSONObject onStreamNoneReader(@RequestBody OnStreamNoneReaderHookParam param) {
        logger.info("[ZLM HOOK]流无人观看:{]->{}->{}/{}" + param.getMediaServerId(), param.getSchema(),
        logger.info("[ZLM HOOK]流无人观看:{}->{}->{}/{}",  param.getMediaServerId(), param.getSchema(),
                param.getApp(), param.getStream());
        JSONObject ret = new JSONObject();
        ret.put("code", 0);
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
@@ -501,8 +501,10 @@
            node.setBasicData(channel);
            node.setParent(false);
            if (channel.getChannelId().length() > 8) {
                if (channel.getChannelId().length() > 13) {
                String gbCodeType = channel.getChannelId().substring(10, 13);
                node.setParent(gbCodeType.equals(ChannelIdType.BUSINESS_GROUP) || gbCodeType.equals(ChannelIdType.VIRTUAL_ORGANIZATION) );
                }
            }else {
                node.setParent(true);
            }
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -757,7 +757,7 @@
                    null);
            return;
        }
        logger.info("[录像下载] deviceId: {}, channelId: {},收流端口:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, ssrcInfo.getPort(), device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck());
        logger.info("[录像下载] deviceId: {}, channelId: {}, 下载速度:{}, 收流端口:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, downloadSpeed, ssrcInfo.getPort(), device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck());
        // 初始化redis中的invite消息状态
        InviteInfo inviteInfo = InviteInfo.getinviteInfo(device.getDeviceId(), channelId, ssrcInfo.getStream(), ssrcInfo,
                mediaServerItem.getSdpIp(), ssrcInfo.getPort(), device.getStreamMode(), InviteSessionType.DOWNLOAD,
@@ -888,7 +888,6 @@
                                        cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null, null);
                                    } catch (InvalidArgumentException | SipException | ParseException | SsrcTransactionNotFoundException e) {
                                        logger.error("[命令发送失败] 停止点播, 发送BYE: {}", e.getMessage());
                                    }
                                    dynamicTask.stop(downLoadTimeOutTaskKey);
@@ -970,10 +969,12 @@
    private StreamInfo onPublishHandlerForDownload(MediaServerItem mediaServerItemInuse, JSONObject response, String deviceId, String channelId, String startTime, String endTime) {
        StreamInfo streamInfo = onPublishHandler(mediaServerItemInuse, response, deviceId, channelId);
        if (streamInfo != null) {
            streamInfo.setProgress(0);
            streamInfo.setStartTime(startTime);
            streamInfo.setEndTime(endTime);
            InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.DOWNLOAD, deviceId, channelId);
            InviteInfo inviteInfo = inviteStreamService.getInviteInfo(InviteSessionType.DOWNLOAD, deviceId, channelId, streamInfo.getStream());
            if (inviteInfo != null) {
                logger.info("[录像下载] 更新invite消息中的stream信息");
                inviteInfo.setStatus(InviteSessionStatus.ok);
                inviteInfo.setStreamInfo(streamInfo);
                inviteStreamService.updateInviteInfo(inviteInfo);
web_src/src/components/GBRecordDetail.vue
@@ -182,9 +182,11 @@
      this.playerStyle["height"] = this.winHeight + "px";
      this.chooseDate = moment().format('YYYY-MM-DD')
      this.dateChange();
      window.addEventListener('beforeunload', this.stopPlayRecord)
        },
        destroyed() {
            this.$destroy('recordVideoPlayer');
      window.removeEventListener('beforeunload', this.stopPlayRecord)
        },
        methods: {
      dateChange(){
@@ -338,6 +340,8 @@
        });
      },
      stopPlayRecord: function (callback) {
        console.log("停止录像回放")
        if (this.streamId !== "") {
        this.$refs["recordVideoPlayer"].pause();
        this.videoUrl = '';
        this.$axios({
@@ -346,6 +350,8 @@
        }).then(function (res) {
          if (callback) callback()
        });
        }
      },
      getDataWidth(item){
        let timeForFile = this.getTimeForFile(item);
@@ -423,8 +429,14 @@
        return hStr + ":" + mStr + ":" + sStr
      },
      goBack(){
        window.history.go(-1);
        // 如果正在进行录像回放则,发送停止
        if (this.streamId !== "") {
          this.stopPlayRecord(()=> {
            this.streamId = "";
          })
      }
        window.history.go(-1);
      },
        }
    };
</script>
web_src/src/components/dialog/recordDownload.vue
@@ -21,7 +21,7 @@
export default {
    name: 'recordDownload',
    created() {
      window.addEventListener('beforeunload', this.stopDownloadRecord)
    },
    data() {
@@ -197,6 +197,9 @@
            console.log(error);
          });
        }
    },
    destroyed() {
      window.removeEventListener('beforeunload', this.stopDownloadRecord)
    }
};
</script>