国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

web實(shí)時預(yù)覽功能開發(fā) java ??祍dk nvr

這篇具有很好參考價值的文章主要介紹了web實(shí)時預(yù)覽功能開發(fā) java ??祍dk nvr。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

1.實(shí)時視頻流解決方案

目錄

1.實(shí)時視頻流解決方案

2.步驟

1.搭建rtmp+flv服務(wù)器

2.java預(yù)覽demo

3.實(shí)時預(yù)覽

1.配置??祍dk庫文件

2.修改FPREVIEW_NEWLINK_CB代碼,推流

3.修改FPREVIEW_DATA_CB代碼,取流

4.javacv的推流

3.部分代碼

1.啟動項(xiàng)目初始化cms,stream的代碼

2.cms代碼

3.stream代碼



1.前端調(diào)用后臺接口,
2.后臺接口調(diào)用??祍dk開啟具體的攝像頭監(jiān)聽,獲取攝像頭實(shí)時流數(shù)據(jù)
3.建立管道,海康sdk監(jiān)聽線程和javacv推流線程共享管道
4.sdk線程向管道輸出流寫數(shù)據(jù),javacv推流線程向rtmp發(fā)送管道數(shù)據(jù)。即sdk生產(chǎn)者,javacv是消費(fèi)者
5.nginx+rtmp+flv模塊接收到視頻流,可以通過http的路徑在瀏覽器訪問

前端->后臺->海康sdk—>管道->javacv->nginx+rtmp+flv->http路徑

2.步驟

1.搭建rtmp+flv服務(wù)器

windows系統(tǒng)下,自己編譯比較麻煩,這邊有大佬編譯好的windows中obs+nginx-http-flv-module的流媒體服務(wù)搭建_windows nginx集成http-flv_OneCodeSolvesAll的博客-CSDN博客個人編譯好的:鏈接:https://pan.baidu.com/s/1XKkyYvK5W6yZA1w2mPaAfg
提取碼:3ug6

linux環(huán)境下,下載nginx-http-flv-module(包含nginx-rtmp-module),添加到nginx重載配置就行,網(wǎng)上有很多教程。

如果不需要flv,也可以單獨(dú)下載nginx-rtmp-module,添加到nginx重載配置。

2.java預(yù)覽demo

1.登錄海康平臺??甸_放平臺

選擇硬件產(chǎn)品的isup sdk下載

海康isupsdk,JAVA,java,實(shí)時音視頻

2.解壓之后

??礽supsdk,JAVA,java,實(shí)時音視頻

?java的這個demo直接打開,修改一下nvr信息,包括ip端口就可以直接預(yù)覽。

3.實(shí)時預(yù)覽

1.配置??祍dk庫文件

??滴臋nlib文件夾下的文件就是庫文件,JavaISUPDemo\lib下也有,需要注意文檔是win還是linux版本的。

2.修改FPREVIEW_NEWLINK_CB代碼,推流

每當(dāng)NET_ECMS_StartGetRealStreamV11,開啟預(yù)覽時,F(xiàn)PREVIEW_NEWLINK_CB便會監(jiān)聽到預(yù)覽請求。

創(chuàng)建管道,分別用于取流推流。異步開始調(diào)用javacv的推流方法。

PipedInputStream pis = new PipedInputStream();
PipedOutputStream pos = new PipedOutputStream();
Stream.streamMap.put("stream:"+lLinkHandle,pos);
pos.connect(pis);
CompletableFuture.runAsync(()-> {
    try {
         PushUtil.grabAndPushRtmp(pis,"rtmp://"+rtmphost+"/live/"+userId+"_"+ dwChannelNo);
    } catch (Exception e) {
         e.printStackTrace();
    }
}, Executors.newFixedThreadPool(1));

3.修改FPREVIEW_DATA_CB代碼,取流

每當(dāng)監(jiān)聽到視頻流時,將視頻流寫入pos管道。注意此處不能使用redis,redis會嚴(yán)重影響此處代碼性能,導(dǎo)致取流失敗。每監(jiān)聽一次,是一個新的線程。第一塊注釋的代碼是調(diào)試時使用,調(diào)試完之后要刪掉。第二塊注釋代碼pos也可以存到map中,使用時從map取,此處直接構(gòu)造方法傳進(jìn)來也可以。

    public class FPREVIEW_DATA_CB implements HCISUPStream.PREVIEW_DATA_CB {

        private PipedOutputStream pos;
        public FPREVIEW_DATA_CB(PipedOutputStream pos) {
            this.pos = pos;
        }

        //實(shí)時流回調(diào)函數(shù)/
        @Override
        public void invoke(int iPreviewHandle, HCISUPStream.NET_EHOME_PREVIEW_CB_MSG pPreviewCBMsg, Pointer pUserData) throws Exception {
//            if (Count == 500) {//降低打印頻率
//                log.info("FPREVIEW_DATA_CB callback, iPreviewHandle:{}", iPreviewHandle);
//                log.info("FPREVIEW_DATA_CB callback, data length:" + pPreviewCBMsg.dwDataLen);
//                Count = 0;
//            }
//            Count++;

            long offset = 0;
            ByteBuffer buffers = pPreviewCBMsg.pRecvdata.getByteBuffer(offset, pPreviewCBMsg.dwDataLen);
            byte[] bytes = new byte[pPreviewCBMsg.dwDataLen];
            buffers.rewind();
            buffers.get(bytes);

            try{
                //2.將數(shù)據(jù)讀入到內(nèi)存空間,此處不可用redis,否則執(zhí)行時間是當(dāng)前10倍
//                PipedOutputStream pos = Stream.streamMap.get("stream:"+iPreviewHandle);
                pos.write(bytes);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

4.javacv的推流

關(guān)于2.提到的javacv推流,linux和windows環(huán)境所需要的依賴包不同。

以下,test的是本地windows環(huán)境使用的,runtime是線上使用的,可不寫,因?yàn)槟J(rèn)就是runtime。

<!-- Linux x86_64 使用 -->
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>javacpp</artifactId>
    <version>1.5.7</version>
</dependency>
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>opencv</artifactId>
    <version>4.5.5-1.5.7</version>
    <classifier>linux-x86_64</classifier>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>openblas</artifactId>
    <version>0.3.19-1.5.7</version>
    <classifier>linux-x86_64</classifier>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>ffmpeg</artifactId>
    <version>5.0-1.5.7</version>
    <classifier>linux-x86_64</classifier>
    <scope>runtime</scope>
</dependency>
<!-- Windows x86_64 使用 -->
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>opencv</artifactId>
    <version>4.5.5-1.5.7</version>
    <classifier>windows-x86_64</classifier>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>openblas</artifactId>
    <version>0.3.19-1.5.7</version>
    <classifier>windows-x86_64</classifier>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>ffmpeg</artifactId>
    <version>5.0-1.5.7</version>
    <classifier>windows-x86_64</classifier>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>javacv</artifactId>
    <version>1.5.7</version>
    <exclusions>
        <exclusion>
            <groupId>org.bytedeco.javacpp-presets</groupId>
            <artifactId>*</artifactId>
        </exclusion>
    </exclusions>
</dependency>

推流代碼原理就是,javacv抓取幀,根據(jù)幀率算出間隔時間推送到rtmp服務(wù)器。

package com.ei.ambulance.util.video;

import org.bytedeco.ffmpeg.avcodec.AVCodecParameters;
import org.bytedeco.ffmpeg.avformat.AVFormatContext;
import org.bytedeco.ffmpeg.avformat.AVStream;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.FFmpegLogCallback;
import org.bytedeco.javacv.Frame;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.PipedInputStream;

/**
 * @author willzhao
 * @version 1.0
 * @description 讀取指定的mp4文件,推送到SRS服務(wù)器
 * @date 2021/11/19 8:49
 */
public class PushUtil {
    private static final Logger log = LoggerFactory.getLogger(PushUtil.class);

    /**
     * 推送到SRS服務(wù)器
     *
     * @param pis
     * @param pushAddress 推流地址
     * @throws Exception
     */
    public static void grabAndPushRtmp(PipedInputStream pis, String pushAddress) throws Exception {
        Thread.sleep(500);
        // ffmepg日志級別
        avutil.av_log_set_level(avutil.AV_LOG_ERROR);
        FFmpegLogCallback.set();
        // 實(shí)例化幀抓取器對象,將文件路徑傳入
        // 1.直接以文件形式實(shí)例化幀抓取器,此方式可以推送h264,ps碼流格式的MP4
//        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(MP4_FILE_PATH);
        // 2.從文件中取流實(shí)例化幀抓取器,此方式只能推送ps碼流的MP4
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(pis,0);

        long startTime = System.currentTimeMillis();

        log.info("開始初始化幀抓取器");
        // 下面兩行設(shè)置可加可不加
        grabber.setOption("analyzeduration", "1000000");
//        grabber.setFormat("h264");
        // 初始化幀抓取器,例如數(shù)據(jù)結(jié)構(gòu)(時間戳、編碼器上下文、幀對象等),
        // 如果入?yún)⒌扔趖rue,還會調(diào)用avformat_find_stream_info方法獲取流的信息,放入AVFormatContext類型的成員變量oc中
        grabber.start(true);
//        grabber.startUnsafe(true); // 也可以使用此方法
        log.info("幀抓取器初始化完成,耗時[{}]毫秒", System.currentTimeMillis()-startTime);

        // grabber.start方法中,初始化的解碼器信息存在放在grabber的成員變量oc中
        AVFormatContext avFormatContext = grabber.getFormatContext();

        // 文件內(nèi)有幾個媒體流(一般是視頻流+音頻流)
        int streamNum = avFormatContext.nb_streams();

        // 沒有媒體流就不用繼續(xù)了
        if (streamNum<1) {
            log.error("文件內(nèi)不存在媒體流");
            return;
        }

        // 取得視頻的幀率
        int frameRate = (int)grabber.getVideoFrameRate();

        log.info("視頻幀率[{}],視頻時長[{}]秒,媒體流數(shù)量[{}]",
                frameRate,
                avFormatContext.duration()/1000000,
                avFormatContext.nb_streams());

        // 遍歷每一個流,檢查其類型
        for (int i=0; i< streamNum; i++) {
            AVStream avStream = avFormatContext.streams(i);
            AVCodecParameters avCodecParameters = avStream.codecpar();
            log.info("流的索引[{}],編碼器類型[{}],編碼器ID[{}]", i, avCodecParameters.codec_type(), avCodecParameters.codec_id());
        }

        // 視頻寬度
        int frameWidth = grabber.getImageWidth();
        // 視頻高度
        int frameHeight = grabber.getImageHeight();
        // 音頻通道數(shù)量
        int audioChannels = grabber.getAudioChannels();

        log.info("視頻寬度[{}],視頻高度[{}],音頻通道數(shù)[{}]",
                frameWidth,
                frameHeight,
                audioChannels);

        // 實(shí)例化FFmpegFrameRecorder,將SRS的推送地址傳入
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(pushAddress,
                frameWidth,
                frameHeight,
                audioChannels);

        // 設(shè)置編碼格式
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);

        // 設(shè)置封裝格式
        recorder.setFormat("flv");

        // 一秒內(nèi)的幀數(shù)
        recorder.setFrameRate(frameRate);

        // 兩個關(guān)鍵幀之間的幀數(shù)
        recorder.setGopSize(frameRate);

        // 設(shè)置音頻通道數(shù),與視頻源的通道數(shù)相等
        recorder.setAudioChannels(grabber.getAudioChannels());

        startTime = System.currentTimeMillis();
        log.info("開始初始化幀抓取器");

        // 初始化幀錄制器,例如數(shù)據(jù)結(jié)構(gòu)(音頻流、視頻流指針,編碼器),
        // 調(diào)用av_guess_format方法,確定視頻輸出時的封裝方式,
        // 媒體上下文對象的內(nèi)存分配,
        // 編碼器的各項(xiàng)參數(shù)設(shè)置
        recorder.start();

        log.info("幀錄制初始化完成,耗時[{}]毫秒", System.currentTimeMillis()-startTime);

        Frame frame;

        startTime = System.currentTimeMillis();

        log.info("開始推流");

        long videoTS = 0;

        int videoFrameNum = 0;
        int audioFrameNum = 0;
        int dataFrameNum = 0;

        // 假設(shè)一秒鐘15幀,那么兩幀間隔就是(1000/15)毫秒
        int interVal = 1000/frameRate;
        // 發(fā)送完一幀后sleep的時間,不能完全等于(1000/frameRate),不然會卡頓,
        // 要更小一些,這里取八分之一
        interVal/=8;

        // 持續(xù)從視頻源取幀
        while (null!=(frame=grabber.grab())) {
            videoTS = 1000 * (System.currentTimeMillis() - startTime);

            // 時間戳
            recorder.setTimestamp(videoTS);

            // 有圖像,就把視頻幀加一
            if (null!=frame.image) {
                videoFrameNum++;
            }

            // 有聲音,就把音頻幀加一
            if (null!=frame.samples) {
                audioFrameNum++;
            }

            // 有數(shù)據(jù),就把數(shù)據(jù)幀加一
            if (null!=frame.data) {
                dataFrameNum++;
            }

            // 取出的每一幀,都推送到SRS
            recorder.record(frame);

            // 停頓一下再推送
            Thread.sleep(interVal);
        }

        log.info("推送完成,視頻幀[{}],音頻幀[{}],數(shù)據(jù)幀[{}],耗時[{}]秒",
                videoFrameNum,
                audioFrameNum,
                dataFrameNum,
                (System.currentTimeMillis()-startTime)/1000);

        // 關(guān)閉幀錄制器
        recorder.close();
        // 關(guān)閉幀抓取器
        grabber.stop();
        grabber.close();
        pis.close();
    }

}

其中,Thread.sleep(500);是必要的。要保證此線程執(zhí)行到后面代碼時,管道中必須存在流,這樣開始初始化幀抓取器才能成功。即取流線程必須先于推流線程執(zhí)行。否則會報(bào)錯。

3.部分代碼

代碼中涉及到部分業(yè)務(wù)代碼,按需修改。文章來源地址http://www.zghlxwxcb.cn/news/detail-573232.html

1.啟動項(xiàng)目初始化cms,stream的代碼

package com.ei.ambulance;

import com.ei.ambulance.mapper.BreastpieceMapper;
import com.ei.ambulance.mapper.BreastpieceVideoMapper;
import com.ei.ambulance.mapper.TaskDetailMapper;
import com.ei.ambulance.util.RedisUtil;
import com.ei.ambulance.util.cacheMap.CacheMap;
import com.ei.ambulance.util.isup.Cms;
import com.ei.ambulance.util.isup.Stream;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * @author zhangyd
 * @date 2022/9/20
 */
@Component
@Slf4j
@Order(1)
public class ISUPIniter implements CommandLineRunner {

    @Value("${hik.cmsServerIP}")
    String cmsServerIp;

    @Value("${hik.cmsServerPort}")
    String cmsServerPort;

    @Value("${hik.voiceSmsServerIP}")
    String voiceSmsServerIp;

    @Value("${hik.voiceSmsServerPort}")
    String voiceSmsServerPort;

    @Value("${hik.breastpieceVideoPath}")
    String breastpieceVideoPath;

    @Value("${rtmp.rtmphost}")
    private String rtmphost;

    @Value("${hik.smsServerIP}")
    String smsServerIP;

    @Value("${hik.smsServerPort}")
    String smsServerPort;

    @Autowired
    RedisUtil redisUtil;

    @Autowired
    BreastpieceMapper breastpieceMapper;

    @Autowired
    TaskDetailMapper taskDetailMapper;

    @Autowired
    BreastpieceVideoMapper breastpieceVideoMapper;

    @Override
    public void run(String... args) throws Exception {
        Cms cms = new Cms();
        cms.redisUtil = redisUtil;
        cms.breastpieceMapper = breastpieceMapper;
        cms.taskDetailMapper = taskDetailMapper;
        cms.breastpieceVideoMapper = breastpieceVideoMapper;
        cms.cMS_Init();
        cms.startCmsListen(cmsServerIp, cmsServerPort, breastpieceVideoPath);

        Stream stream = new Stream();
        stream.eStream_Init();
        stream.startRealPlayListen(smsServerIP, smsServerPort);
        Stream.redisUtil = redisUtil;
        Stream.rtmphost = rtmphost;
        CacheMap.put("stream", stream);
        CacheMap.put("cms", cms);
        redisUtil.deletePattern("video:*");
    }
}

2.cms代碼

package com.ei.ambulance.util.isup;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.ei.ambulance.mapper.BreastpieceMapper;
import com.ei.ambulance.mapper.BreastpieceVideoMapper;
import com.ei.ambulance.mapper.TaskDetailMapper;
import com.ei.ambulance.model.Breastpiece;
import com.ei.ambulance.model.BreastpieceVideo;
import com.ei.ambulance.model.ambulanceManage.TaskDetail;
import com.ei.ambulance.util.RedisUtil;
import com.ei.ambulance.util.Xml2JsonUtil;
import com.ei.ambulance.util.cacheMap.CacheMap;
import com.ei.ambulance.util.hik.OsSelect;
import com.ei.ambulance.vo.video.VideoFileInfoVo;
import com.ei.ambulance.vo.video.VideoFilesReq;
import com.sun.istack.internal.NotNull;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.DocumentException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author zhangyd
 * @date 2022/9/20
 */
@Slf4j
public class Cms {

    public static Map<String,Integer> userLoginMap  = new HashMap<>();

    public RedisUtil redisUtil;

    public BreastpieceMapper breastpieceMapper;

    public TaskDetailMapper taskDetailMapper;

    public BreastpieceVideoMapper breastpieceVideoMapper;

    public static HCISUPCMS hCEhomeCMS = null;
    //CMS監(jiān)聽句柄
    public static int CmsHandle = -1;
    //注冊回調(diào)函數(shù)實(shí)現(xiàn)
    static FRegisterCallBack fRegisterCallBack;
    HCISUPCMS.NET_EHOME_CMS_LISTEN_PARAM struCMSListenPara = new HCISUPCMS.NET_EHOME_CMS_LISTEN_PARAM();


    /**
     * 根據(jù)不同操作系統(tǒng)選擇不同的庫文件和庫路徑
     *
     * @return
     */
    private static boolean createSDKInstance() {
        if (hCEhomeCMS == null) {
            synchronized (HCISUPCMS.class) {
                String strDllPath = "";
                try {
                    if (OsSelect.isWindows()) {
                        //win系統(tǒng)加載庫路徑(路徑不要帶中文)
                        strDllPath = System.getProperty("user.dir") + "\\lib\\isupsdk\\HCISUPCMS.dll";
                    } else if (OsSelect.isLinux()) {
                        //Linux系統(tǒng)加載庫路徑(路徑不要帶中文)
                        strDllPath = System.getProperty("user.dir") + "/lib/isupsdkLinux/libHCISUPCMS.so";
                        log.info("===============1{}", strDllPath);
//                        strDllPath = "/usr/soft/java-service/ambulance/lib/isupsdkLinux/libHCISUPCMS.so";
                    }
                    hCEhomeCMS = (HCISUPCMS) Native.loadLibrary(strDllPath, HCISUPCMS.class);
                } catch (Exception ex) {
                    log.info("loadLibrary: " + strDllPath + " Error: " + ex.getMessage());
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * cms服務(wù)初始化,開啟監(jiān)聽
     *
     * @throws IOException
     */
    public void cMS_Init() throws IOException {

        if (hCEhomeCMS == null) {
            if (!createSDKInstance()) {
                log.info("Load CMS SDK fail");
                return;
            }
        }
        if (OsSelect.isWindows()) {
            HCISUPCMS.BYTE_ARRAY ptrByteArrayCrypto = new HCISUPCMS.BYTE_ARRAY(256);
            String strPathCrypto = System.getProperty("user.dir") + "\\lib\\isupsdk\\libeay32.dll"; //Linux版本是libcrypto.so庫文件的路徑
            System.arraycopy(strPathCrypto.getBytes(), 0, ptrByteArrayCrypto.byValue, 0, strPathCrypto.length());
            ptrByteArrayCrypto.write();
            hCEhomeCMS.NET_ECMS_SetSDKInitCfg(0, ptrByteArrayCrypto.getPointer());

            //設(shè)置libssl.so所在路徑
            HCISUPCMS.BYTE_ARRAY ptrByteArraySsl = new HCISUPCMS.BYTE_ARRAY(256);
            String strPathSsl = System.getProperty("user.dir") + "\\lib\\isupsdk\\ssleay32.dll";    //Linux版本是libssl.so庫文件的路徑
            System.arraycopy(strPathSsl.getBytes(), 0, ptrByteArraySsl.byValue, 0, strPathSsl.length());
            ptrByteArraySsl.write();
            hCEhomeCMS.NET_ECMS_SetSDKInitCfg(1, ptrByteArraySsl.getPointer());
            //注冊服務(wù)初始化
            boolean binit = hCEhomeCMS.NET_ECMS_Init();
            //設(shè)置HCAapSDKCom組件庫文件夾所在路徑
            HCISUPCMS.BYTE_ARRAY ptrByteArrayCom = new HCISUPCMS.BYTE_ARRAY(256);
            String strPathCom = System.getProperty("user.dir") + "\\lib\\isupsdk\\HCAapSDKCom";        //只支持絕對路徑,建議使用英文路徑
            System.arraycopy(strPathCom.getBytes(), 0, ptrByteArrayCom.byValue, 0, strPathCom.length());
            ptrByteArrayCom.write();
            hCEhomeCMS.NET_ECMS_SetSDKLocalCfg(5, ptrByteArrayCom.getPointer());

        } else if (OsSelect.isLinux()) {
            //todo linux版本的sdk
            HCISUPCMS.BYTE_ARRAY ptrByteArrayCrypto = new HCISUPCMS.BYTE_ARRAY(256);
            String strPathCrypto = System.getProperty("user.dir") + "/lib/isupsdkLinux/libcrypto.so"; //Linux版本是libcrypto.so庫文件的路徑
            log.info("===============2{}", strPathCrypto);
            System.arraycopy(strPathCrypto.getBytes(), 0, ptrByteArrayCrypto.byValue, 0, strPathCrypto.length());
            ptrByteArrayCrypto.write();
            hCEhomeCMS.NET_ECMS_SetSDKInitCfg(0, ptrByteArrayCrypto.getPointer());

            //設(shè)置libssl.so所在路徑
            HCISUPCMS.BYTE_ARRAY ptrByteArraySsl = new HCISUPCMS.BYTE_ARRAY(256);
            String strPathSsl = System.getProperty("user.dir") + "/lib/isupsdkLinux/libssl.so";    //Linux版本是libssl.so庫文件的路徑
            log.info("===============3{}", strPathSsl);
            System.arraycopy(strPathSsl.getBytes(), 0, ptrByteArraySsl.byValue, 0, strPathSsl.length());
            ptrByteArraySsl.write();
            hCEhomeCMS.NET_ECMS_SetSDKInitCfg(1, ptrByteArraySsl.getPointer());
            //注冊服務(wù)初始化
            boolean binit = hCEhomeCMS.NET_ECMS_Init();
            //設(shè)置HCAapSDKCom組件庫文件夾所在路徑
            HCISUPCMS.BYTE_ARRAY ptrByteArrayCom = new HCISUPCMS.BYTE_ARRAY(256);
            String strPathCom = System.getProperty("user.dir") + "/lib/isupsdkLinux/HCAapSDKCom/";        //只支持絕對路徑,建議使用英文路徑
            log.info("===============4{}", strPathCom);
            System.arraycopy(strPathCom.getBytes(), 0, ptrByteArrayCom.byValue, 0, strPathCom.length());
            ptrByteArrayCom.write();
            hCEhomeCMS.NET_ECMS_SetSDKLocalCfg(5, ptrByteArrayCom.getPointer());

        }
        hCEhomeCMS.NET_ECMS_SetLogToFile(3, System.getProperty("user.dir") + "/EHomeSDKLog", false);
    }

    public void startCmsListen(String cmsServerIp, String cmsServerPort, String breastpieceVideoPath) {
        if (fRegisterCallBack == null) {
            fRegisterCallBack = new FRegisterCallBack();
            fRegisterCallBack.ip = cmsServerIp;
            fRegisterCallBack.port = "8007";
            fRegisterCallBack.breastpieceVideoPath = breastpieceVideoPath;
        }
        System.arraycopy(cmsServerIp.getBytes(), 0, struCMSListenPara.struAddress.szIP, 0, cmsServerIp.length());
        struCMSListenPara.struAddress.wPort = Short.parseShort(cmsServerPort);
        struCMSListenPara.fnCB = fRegisterCallBack;
        struCMSListenPara.write();
        //啟動監(jiān)聽,接收設(shè)備注冊信息
        CmsHandle = hCEhomeCMS.NET_ECMS_StartListen(struCMSListenPara);
        if (CmsHandle < -1) {
            log.info("NET_ECMS_StartListen failed, error code:" + hCEhomeCMS.NET_ECMS_GetLastError());
            hCEhomeCMS.NET_ECMS_Fini();
            return;
        }
        String cmsListenInfo = new String(struCMSListenPara.struAddress.szIP).trim() + "_" + struCMSListenPara.struAddress.wPort;
        log.info("注冊服務(wù)器:" + cmsListenInfo + ",NET_ECMS_StartListen succeed!\n");
    }

    public boolean setHeart(int lUserID, long dwKeepAliveSec, long dwTimeOutCount) {
        boolean result = hCEhomeCMS.NET_ECMS_SetAliveTimeout(lUserID, dwKeepAliveSec, dwTimeOutCount);
        if (result) {
            log.info("device NET_ECMS_SetAliveTimeout success");
        } else {
            log.info("device NET_ECMS_SetAliveTimeout failed, error code: {}", hCEhomeCMS.NET_ECMS_GetLastError());
        }
        return result;
    }

    public String channels(int channel, int lUserID) throws DocumentException {
        HCISUPCMS.NET_EHOME_PTXML_PARAM m_struParam = new HCISUPCMS.NET_EHOME_PTXML_PARAM();
        m_struParam.read();
        String url = "GET /ISAPI/ContentMgmt/InputProxy/channels";
        HCISUPCMS.BYTE_ARRAY ptrUrl = new HCISUPCMS.BYTE_ARRAY(1024);
        System.arraycopy(url.getBytes(), 0, ptrUrl.byValue, 0, url.length());
        ptrUrl.write();
        m_struParam.pRequestUrl = ptrUrl.getPointer();
        m_struParam.dwRequestUrlLen = url.length();

        HCISUPCMS.BYTE_ARRAY ptrOutByte = new HCISUPCMS.BYTE_ARRAY(100 * 1024);
        m_struParam.pOutBuffer = ptrOutByte.getPointer();
        m_struParam.dwOutSize = 100 * 1024;
        m_struParam.write();

        if (!hCEhomeCMS.NET_ECMS_ISAPIPassThrough(lUserID, m_struParam)) {
            int iErr = hCEhomeCMS.NET_ECMS_GetLastError();
            log.info("NET_ECMS_ISAPIPassThrough failed, error:{}", iErr);
            m_struParam.read();
            ptrOutByte.read();
            log.info("ptrOutByte:{}", new String(ptrOutByte.byValue).trim());
        }
        String xml = new String(m_struParam.pOutBuffer.getByteArray(0, m_struParam.dwOutSize));
        xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + xml;
        JSONObject result = Xml2JsonUtil.xml2Json(xml);
        JSONArray jsonArray = result.getJSONArray("inputproxychannel");
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject j = jsonArray.getJSONObject(i);
            if (j.getInteger("id") == channel) {
                return j.getJSONObject("sourceinputportdescriptor").getString("ipaddress");
            }
        }
        return null;
    }

    public List<Integer> cameraList(int lUserID) throws DocumentException {
        HCISUPCMS.NET_EHOME_PTXML_PARAM m_struParam = new HCISUPCMS.NET_EHOME_PTXML_PARAM();
        m_struParam.read();
        String url = "GET /ISAPI/ContentMgmt/InputProxy/channels";
        HCISUPCMS.BYTE_ARRAY ptrUrl = new HCISUPCMS.BYTE_ARRAY(1024);
        System.arraycopy(url.getBytes(), 0, ptrUrl.byValue, 0, url.length());
        ptrUrl.write();
        m_struParam.pRequestUrl = ptrUrl.getPointer();
        m_struParam.dwRequestUrlLen = url.length();

        HCISUPCMS.BYTE_ARRAY ptrOutByte = new HCISUPCMS.BYTE_ARRAY(100 * 1024);
        m_struParam.pOutBuffer = ptrOutByte.getPointer();
        m_struParam.dwOutSize = 100 * 1024;
        m_struParam.write();

        if (!hCEhomeCMS.NET_ECMS_ISAPIPassThrough(lUserID, m_struParam)) {
            int iErr = hCEhomeCMS.NET_ECMS_GetLastError();
            log.info("NET_ECMS_ISAPIPassThrough failed, error:{}", iErr);
            m_struParam.read();
            ptrOutByte.read();
            log.info("ptrOutByte:{}", new String(ptrOutByte.byValue).trim());
        }
        String xml = new String(m_struParam.pOutBuffer.getByteArray(0, m_struParam.dwOutSize));
        xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + xml;
        JSONObject resultJson = Xml2JsonUtil.xml2Json(xml);
        JSONArray jsonArray = resultJson.getJSONArray("inputproxychannel");
        List<Integer> result = new ArrayList<>();
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject j = jsonArray.getJSONObject(i);
            result.add(j.getInteger("id"));
        }
        return result;
    }

    public void playBack(int lUserID, String ip, String port, @NotNull Date start, @NotNull Date end, String fileName, Integer taskId, Integer breastpieceId) {
        HCISUPCMS.NET_EHOME_PLAYBACK_INFO_IN pPlaybackInfoIn = new HCISUPCMS.NET_EHOME_PLAYBACK_INFO_IN();
        pPlaybackInfoIn.read();
        pPlaybackInfoIn.dwSize = pPlaybackInfoIn.size();
        pPlaybackInfoIn.dwChannel = 1;

        pPlaybackInfoIn.byPlayBackMode = 1;
        pPlaybackInfoIn.unionPlayBackMode.setType(HCISUPCMS.NET_EHOME_PLAYBACKBYTIME.class);
        Calendar cal = Calendar.getInstance();
        cal.setTime(start);
        pPlaybackInfoIn.unionPlayBackMode.struPlayBackbyTime.struStartTime.wYear = (short) cal.get(Calendar.YEAR);
        pPlaybackInfoIn.unionPlayBackMode.struPlayBackbyTime.struStartTime.byMonth = (byte) (cal.get(Calendar.MONTH) + 1);
        pPlaybackInfoIn.unionPlayBackMode.struPlayBackbyTime.struStartTime.byDay = (byte) cal.get(Calendar.DAY_OF_MONTH);
        pPlaybackInfoIn.unionPlayBackMode.struPlayBackbyTime.struStartTime.byHour = (byte) cal.get(Calendar.HOUR_OF_DAY);
        pPlaybackInfoIn.unionPlayBackMode.struPlayBackbyTime.struStartTime.byMinute = (byte) cal.get(Calendar.MINUTE);
        pPlaybackInfoIn.unionPlayBackMode.struPlayBackbyTime.struStartTime.bySecond = (byte) cal.get(Calendar.SECOND);

        cal.setTime(end);
        pPlaybackInfoIn.unionPlayBackMode.struPlayBackbyTime.struStopTime.wYear = (short) cal.get(Calendar.YEAR);
        pPlaybackInfoIn.unionPlayBackMode.struPlayBackbyTime.struStopTime.byMonth = (byte) (cal.get(Calendar.MONTH) + 1);
        pPlaybackInfoIn.unionPlayBackMode.struPlayBackbyTime.struStopTime.byDay = (byte) cal.get(Calendar.DAY_OF_MONTH);
        pPlaybackInfoIn.unionPlayBackMode.struPlayBackbyTime.struStopTime.byHour = (byte) cal.get(Calendar.HOUR_OF_DAY);
        pPlaybackInfoIn.unionPlayBackMode.struPlayBackbyTime.struStopTime.byMinute = (byte) cal.get(Calendar.MINUTE);
        pPlaybackInfoIn.unionPlayBackMode.struPlayBackbyTime.struStopTime.bySecond = (byte) cal.get(Calendar.SECOND);

        System.arraycopy(ip.getBytes(), 0, pPlaybackInfoIn.struStreamSever.szIP, 0, ip.length());
        pPlaybackInfoIn.struStreamSever.wPort = Short.parseShort(port);
        pPlaybackInfoIn.write();
        HCISUPCMS.NET_EHOME_PLAYBACK_INFO_OUT pPlaybackInfoOut = new HCISUPCMS.NET_EHOME_PLAYBACK_INFO_OUT();
        pPlaybackInfoOut.write();
        log.info("NET_ECMS_StartPlayBack接口參數(shù):{}", pPlaybackInfoIn);
        if (hCEhomeCMS.NET_ECMS_StartPlayBack(lUserID, pPlaybackInfoIn, pPlaybackInfoOut)) {
            pPlaybackInfoOut.read();
            log.info("NET_ECMS_StartPlayBack success");
        } else {
            log.info("NET_ECMS_StartPlayBack failed, error code: {}", hCEhomeCMS.NET_ECMS_GetLastError());
            return;
        }
        HCISUPCMS.NET_EHOME_PUSHPLAYBACK_IN m_struPushPlayBackIn = new HCISUPCMS.NET_EHOME_PUSHPLAYBACK_IN();
        m_struPushPlayBackIn.read();
        m_struPushPlayBackIn.dwSize = m_struPushPlayBackIn.size();
        m_struPushPlayBackIn.lSessionID = pPlaybackInfoOut.lSessionID;
        m_struPushPlayBackIn.write();

        HCISUPCMS.NET_EHOME_PUSHPLAYBACK_OUT m_struPushPlayBackOut = new HCISUPCMS.NET_EHOME_PUSHPLAYBACK_OUT();
        m_struPushPlayBackOut.read();
        m_struPushPlayBackOut.dwSize = m_struPushPlayBackOut.size();
        m_struPushPlayBackOut.write();
        log.info("NET_ECMS_StartPushPlayBack接口參數(shù):{}", m_struPushPlayBackIn);
        if (hCEhomeCMS.NET_ECMS_StartPushPlayBack(lUserID, m_struPushPlayBackIn, m_struPushPlayBackOut)) {
            log.info("NET_ECMS_StartPushPlayBack success");
            redisUtil.set("downloadHandle:" + m_struPushPlayBackOut.lHandle, fileName);
            BreastpieceVideo breastpieceVideo = new BreastpieceVideo();
            String[] names = fileName.split(OsSelect.isLinux()? "/" : "\\\\");
            breastpieceVideo.setTaskId(taskId);
            breastpieceVideo.setBreastpieceId(breastpieceId);
            breastpieceVideo.setName(names[names.length - 1] + ".mp4");
            breastpieceVideo.setAddress("http://47.101.185.231/ambulance-pc/video/breast/");
            breastpieceVideo.setStartTime(start);
            breastpieceVideo.setEndTime(end);
            breastpieceVideoMapper.insert(breastpieceVideo);
        } else {
            log.info("NET_ECMS_StartPushPlayBack failed, error code: {}", hCEhomeCMS.NET_ECMS_GetLastError());
        }

    }

    //注冊回調(diào)函數(shù)
    public class FRegisterCallBack implements HCISUPCMS.DEVICE_REGISTER_CB {
        public String ip, port, breastpieceVideoPath;


        @Override
        public boolean invoke(int lUserID, int dwDataType, Pointer pOutBuffer, int dwOutLen, Pointer pInBuffer, int dwInLen, Pointer pUser) {
            log.info("FRegisterCallBack, dwDataType:" + dwDataType + ", lUserID:" + lUserID);
            HCISUPCMS.NET_EHOME_DEV_REG_INFO_V12 strDevRegInfo;
            Pointer pDevRegInfo;
            if (dwDataType == 0 || dwDataType == 7) {
                strDevRegInfo = new HCISUPCMS.NET_EHOME_DEV_REG_INFO_V12();
                strDevRegInfo.write();
                pDevRegInfo = strDevRegInfo.getPointer();
                pDevRegInfo.write(0, pOutBuffer.getByteArray(0, strDevRegInfo.size()), 0, strDevRegInfo.size());
                strDevRegInfo.read();
                HCISUPCMS.NET_EHOME_SERVER_INFO_V50 strEhomeServerInfo = new HCISUPCMS.NET_EHOME_SERVER_INFO_V50();
                strEhomeServerInfo.read();
                byte[] byCmsIP = new byte[0];
                log.info(new String(byCmsIP));
                String nvrCode = new String(strDevRegInfo.struRegInfo.byDeviceID).trim();
                String nvrIp = new String(strDevRegInfo.struRegInfo.struDevAdd.szIP).trim();
                log.info("Device online, DeviceID is:" + nvrCode);
                log.info("Device online, DeviceIP is:" + nvrIp);
                // 設(shè)備注冊上線標(biāo)志
                userLoginMap.put(nvrCode,lUserID);
                redisUtil.set("ip:" + nvrCode, nvrIp);
                redisUtil.set("lUserID:" + nvrCode, lUserID);
                redisUtil.set("carNo:" + lUserID, nvrCode);
                if (nvrCode.startsWith("xp")) {
                    UpdateWrapper<Breastpiece> updateWrapper = new UpdateWrapper<>();
                    updateWrapper.eq("name", nvrCode);
                    Breastpiece breastpiece = new Breastpiece();
                    breastpiece.setIsOnline(1);
                    breastpieceMapper.update(breastpiece, updateWrapper);
                    QueryWrapper<Breastpiece> queryWrapper = new QueryWrapper<>();
                    queryWrapper.eq("name", nvrCode);
                    Breastpiece breastpieceL = breastpieceMapper.selectOne(queryWrapper);
                    //異步配置心跳監(jiān)聽。100秒沒有收到心跳,設(shè)備離線
                    ExecutorService executorService = Executors.newSingleThreadExecutor();
                    executorService.submit(() -> {
                        try {
                            Thread.sleep(2000);
                            boolean heart = hCEhomeCMS.NET_ECMS_SetAliveTimeout(lUserID, 100L, 1L);
                            if (heart) {
                                log.info("device {} NET_ECMS_SetAliveTimeout success", nvrCode);
                            } else {
                                log.info("device {} NET_ECMS_SetAliveTimeout failed, error code: {}", nvrCode, hCEhomeCMS.NET_ECMS_GetLastError());
                            }
                            Stream stream = CacheMap.get("stream");

                            stream.startListenPlayBack(ip, port);
                            List<TaskDetail> taskList = taskDetailMapper.selectListByDeviceCode(nvrCode);
                            if (taskList != null && taskList.size() > 0) {
                                taskList.forEach(t -> {
                                    QueryWrapper<BreastpieceVideo> wrapper = new QueryWrapper<>();
                                    wrapper.eq("task_id", t.getId());
                                    Integer c = breastpieceVideoMapper.selectCount(wrapper);
                                    if (c <= 0) {
                                        playBack(lUserID, "47.101.185.231", port, t.getReceiveTime(), t.getDeliveryTime(), breastpieceVideoPath + t.getId(), t.getId(), breastpieceL.getId());
                                    }
                                });
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    });
                    executorService.shutdown();
                }
                return true;
            } else if (dwDataType == 3) {
                strDevRegInfo = new HCISUPCMS.NET_EHOME_DEV_REG_INFO_V12();
                strDevRegInfo.write();
                pDevRegInfo = strDevRegInfo.getPointer();
                pDevRegInfo.write(0, pOutBuffer.getByteArray(0, strDevRegInfo.size()), 0, strDevRegInfo.size());
                strDevRegInfo.read();
                String szEHomeKey = "12345678";
                byte[] bs = szEHomeKey.getBytes();
                pInBuffer.write(0, bs, 0, szEHomeKey.length());
            } else if (dwDataType == 4) {
                strDevRegInfo = new HCISUPCMS.NET_EHOME_DEV_REG_INFO_V12();
                strDevRegInfo.write();
                pDevRegInfo = strDevRegInfo.getPointer();
                pDevRegInfo.write(0, pOutBuffer.getByteArray(0, strDevRegInfo.size()), 0, strDevRegInfo.size());
                strDevRegInfo.read();

                log.info("byDeviceID:" + new String(strDevRegInfo.struRegInfo.byDeviceID).trim());
                log.info("bySessionKey:" + new String(strDevRegInfo.struRegInfo.bySessionKey).trim());

                HCISUPCMS.NET_EHOME_DEV_SESSIONKEY struSessionKey = new HCISUPCMS.NET_EHOME_DEV_SESSIONKEY();
                System.arraycopy(strDevRegInfo.struRegInfo.byDeviceID, 0, struSessionKey.sDeviceID, 0, strDevRegInfo.struRegInfo.byDeviceID.length);
                System.arraycopy(strDevRegInfo.struRegInfo.bySessionKey, 0, struSessionKey.sSessionKey, 0, strDevRegInfo.struRegInfo.bySessionKey.length);
                struSessionKey.write();

                Pointer pSessionKey = struSessionKey.getPointer();

                hCEhomeCMS.NET_ECMS_SetDeviceSessionKey(pSessionKey);
//                mHCEHomeAlarm.NET_EALARM_SetDeviceSessionKey(pSessionKey);
            } else if (dwDataType == 5) {
                String dasInfo = "{\n" +
                        "    \"Type\":\"DAS\",\n" +
                        "    \"DasInfo\":{\n" +
                        "        \"Address\":\"47.101.185.231\",\n" +
                        "        \"Domain\":\"\",\n" +
                        "        \"ServerID\":\"\",\n" +
                        "        \"Port\":20000,\n" +
                        "        \"UdpPort\":\n" +
                        "    }\n" +
                        "}";
                byte[] bs1 = dasInfo.getBytes();
                pInBuffer.write(0, bs1, 0, dasInfo.length());
            } else if (dwDataType == 1) {
                //設(shè)備離線
                String deviceName = redisUtil.get("carNo:" + lUserID);
                log.info("設(shè)備{}離線", deviceName);
                if (deviceName.startsWith("xp")) {
                    //胸牌
                    UpdateWrapper<Breastpiece> updateWrapper = new UpdateWrapper<>();
                    updateWrapper.eq("name", deviceName);
                    Breastpiece breastpiece = new Breastpiece();
                    breastpiece.setIsOnline(0);
                    breastpieceMapper.update(breastpiece, updateWrapper);
                }
                redisUtil.delete("carNo:" + lUserID);
                redisUtil.delete("ip:" + deviceName);
                redisUtil.delete("lUserID:" + deviceName);
                userLoginMap.remove(deviceName);
            } else if (dwDataType == 8) {
                //心跳
                log.info("__心跳___");
                log.info("FRegisterCallBack default type:" + dwDataType);
            } else {
                log.info("FRegisterCallBack default type:" + dwDataType);
            }
            return true;
        }
    }

    public List<VideoFileInfoVo> findFile(int lLoginID, VideoFilesReq req) throws InterruptedException {
        List<VideoFileInfoVo> result = new ArrayList<>();
        HCISUPCMS.NET_EHOME_REC_FILE_COND strufindCond = new HCISUPCMS.NET_EHOME_REC_FILE_COND();
        strufindCond.dwChannel = 1;
        strufindCond.dwRecType = 0xff;
        strufindCond.dwStartIndex = 0;
        strufindCond.dwMaxFileCountPer = 10;

        Calendar c = Calendar.getInstance();
        c.setTime(req.getStart());
        strufindCond.struStartTime.wYear = (short) c.get(Calendar.YEAR);
        strufindCond.struStartTime.byMonth = (byte) (c.get(Calendar.MONTH) + 1);
        strufindCond.struStartTime.byDay = (byte) c.get(Calendar.DAY_OF_MONTH);
        strufindCond.struStartTime.byHour = (byte) c.get(Calendar.HOUR_OF_DAY);
        strufindCond.struStartTime.byMinute = (byte) c.get(Calendar.MINUTE);
        strufindCond.struStartTime.bySecond = (byte) c.get(Calendar.SECOND);
        c.setTime(req.getEnd());
        strufindCond.struStopTime.wYear = (short) c.get(Calendar.YEAR);
        strufindCond.struStopTime.byMonth = (byte) (c.get(Calendar.MONTH) + 1);
        strufindCond.struStopTime.byDay = (byte) c.get(Calendar.DAY_OF_MONTH);
        strufindCond.struStopTime.byHour = (byte) c.get(Calendar.HOUR_OF_DAY);
        strufindCond.struStopTime.byMinute = (byte) c.get(Calendar.MINUTE);
        strufindCond.struStopTime.bySecond = (byte) c.get(Calendar.SECOND);

        int lHandle = hCEhomeCMS.NET_ECMS_StartFindFile_V11(lLoginID, 0, strufindCond, strufindCond.size());
        if (lHandle < 0) {
            log.info("NET_ECMS_StartFindFile_V11 failed, error code: {}", hCEhomeCMS.NET_ECMS_GetLastError());
        } else {
            log.info("NET_ECMS_StartFindFile_V11 success!");
            while (true) {
                HCISUPCMS.NET_EHOME_REC_FILE struFileInfo = new HCISUPCMS.NET_EHOME_REC_FILE();
                int lRet = hCEhomeCMS.NET_ECMS_FindNextFile_V11(lHandle, struFileInfo, struFileInfo.size());
                if (lRet == 1000) {
                    //保存獲取到的文件
                    VideoFileInfoVo vo = new VideoFileInfoVo();
                    vo.setFileName(new String(struFileInfo.sFileName));
                    log.info(vo.getFileName());
                    String fileSize;
                    if (struFileInfo.dwFileSize / 1024 == 0) {
                        fileSize = String.valueOf(struFileInfo.dwFileSize);
                    } else if (struFileInfo.dwFileSize / 1024 > 0 && struFileInfo.dwFileSize / (1024 * 1024) == 0) {
                        fileSize = struFileInfo.dwFileSize / 1024 + "K";
                    } else {
                        fileSize = struFileInfo.dwFileSize / (1024 * 1024) + "M";
                    }
                    vo.setSize(fileSize);
                    vo.setStart(String.format("%04d-%02d-%02d %02d:%02d:%02d", struFileInfo.struStartTime.wYear, struFileInfo.struStartTime.byMonth, struFileInfo.struStartTime.byDay, struFileInfo.struStartTime.byHour, struFileInfo.struStartTime.byMinute, struFileInfo.struStartTime.bySecond));
                    vo.setEnd(String.format("%04d-%02d-%02d %02d:%02d:%02d", struFileInfo.struStopTime.wYear, struFileInfo.struStopTime.byMonth, struFileInfo.struStopTime.byDay, struFileInfo.struStopTime.byHour, struFileInfo.struStopTime.byMinute, struFileInfo.struStopTime.bySecond));
                    result.add(vo);
                } else if (lRet == 1002) {
                    Thread.sleep(5L);
                } else {
                    break;
                }
            }
            hCEhomeCMS.NET_ECMS_StopFindFile(lHandle);

        }
        return result;
    }

}

3.stream代碼

package com.ei.ambulance.util.isup;

import com.ei.ambulance.util.RedisUtil;
import com.ei.ambulance.util.hik.HCNetSDK;
import com.ei.ambulance.util.hik.OsSelect;
import com.ei.ambulance.util.video.PushUtil;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;

@Slf4j
public class Stream {
    public static Map<String,PipedOutputStream> streamMap = new HashMap<>();
    public static RedisUtil redisUtil;
    public static String rtmphost;
    public static HCISUPStream hCEhomeStream = null;
    public static PlayCtrl playCtrl = null;
    static int m_lPlayBackLinkHandle = -1;   //回放句柄
    public static int m_lPlayBackListenHandle = -1; //回放監(jiān)聽句柄

    public static int StreamHandle = -1;   //預(yù)覽監(jiān)聽句柄
    public static Map<String,Integer> sessionMap = new HashMap<>(); //預(yù)覽sessionID
    public static Map<String,Integer> playHandleMap = new HashMap<>();
    static int backSessionID = -1;  //回放sessionID
    static int Count = 0;
    static int iCount = 0;
    static IntByReference m_lPort = new IntByReference(-1);//回調(diào)預(yù)覽時播放庫端口指針

    HCISUPStream.NET_EHOME_PLAYBACK_LISTEN_PARAM struPlayBackListen = new HCISUPStream.NET_EHOME_PLAYBACK_LISTEN_PARAM();
//    HCISUPStream.NET_EHOME_LISTEN_PREVIEW_CFG struPreviewListen = new HCISUPStream.NET_EHOME_LISTEN_PREVIEW_CFG();
    static FPREVIEW_NEWLINK_CB fPREVIEW_NEWLINK_CB;//預(yù)覽監(jiān)聽回調(diào)函數(shù)實(shí)現(xiàn)
//    static FPREVIEW_DATA_CB fPREVIEW_DATA_CB;//預(yù)覽回調(diào)函數(shù)實(shí)現(xiàn)
    public static Map<String,FPREVIEW_DATA_CB> dataMap = new HashMap<>();


    static PLAYBACK_NEWLINK_CB fPLAYBACK_NEWLINK_CB; //回放監(jiān)聽回調(diào)函數(shù)實(shí)現(xiàn)
    static PLAYBACK_DATA_CB fPLAYBACK_DATA_CB;   //回放回調(diào)實(shí)現(xiàn)

    /**
     * 動態(tài)庫加載
     *
     * @return
     */
    private static boolean CreateSDKInstance() {
        if (hCEhomeStream == null) {
            synchronized (HCISUPStream.class) {
                String strDllPath = "";
                try {
                    if (OsSelect.isWindows())
                        //win系統(tǒng)加載庫路徑
                        strDllPath = System.getProperty("user.dir") + "\\lib\\isupsdk\\HCISUPStream.dll";

                    else if (OsSelect.isLinux())
                        //Linux系統(tǒng)加載庫路徑
                        strDllPath = System.getProperty("user.dir") + "/lib/isupsdkLinux/libHCISUPStream.so";
                    hCEhomeStream = (HCISUPStream) Native.loadLibrary(strDllPath, HCISUPStream.class);
                } catch (Exception ex) {
                    log.info("loadLibrary: " + strDllPath + " Error: " + ex.getMessage());
                    return false;
                }
            }
        }
        return true;
    }

    public void eStream_Init() {
        if (hCEhomeStream == null) {
            if (!CreateSDKInstance()) {
                log.info("Load Stream SDK fail");
                return;
            } else {
                log.info("Load Stream SDK success");
            }
        }
//        if (playCtrl == null) {
//            if (!CreatePlayInstance()) {
//                log.info("Load PlayCtrl fail");
//                return;
//            } else {
//                log.info("Load PlayCtrl SDK success");
//            }
//
//        }
        if (OsSelect.isWindows()) {
            HCISUPCMS.BYTE_ARRAY ptrByteArrayCrypto = new HCISUPCMS.BYTE_ARRAY(256);
            String strPathCrypto = System.getProperty("user.dir") + "\\lib\\isupsdk\\libeay32.dll"; //Linux版本是libcrypto.so庫文件的路徑
            System.arraycopy(strPathCrypto.getBytes(), 0, ptrByteArrayCrypto.byValue, 0, strPathCrypto.length());
            ptrByteArrayCrypto.write();
            if (!hCEhomeStream.NET_ESTREAM_SetSDKInitCfg(0, ptrByteArrayCrypto.getPointer())) {
                log.info("NET_ESTREAM_SetSDKInitCfg 0 failed, error:" + hCEhomeStream.NET_ESTREAM_GetLastError());
            }
            HCISUPCMS.BYTE_ARRAY ptrByteArraySsl = new HCISUPCMS.BYTE_ARRAY(256);
            String strPathSsl = System.getProperty("user.dir") + "\\lib\\isupsdk\\ssleay32.dll";    //Linux版本是libssl.so庫文件的路徑
            System.arraycopy(strPathSsl.getBytes(), 0, ptrByteArraySsl.byValue, 0, strPathSsl.length());
            ptrByteArraySsl.write();
            if (!hCEhomeStream.NET_ESTREAM_SetSDKInitCfg(1, ptrByteArraySsl.getPointer())) {
                log.info("NET_ESTREAM_SetSDKInitCfg 1 failed, error:" + hCEhomeStream.NET_ESTREAM_GetLastError());
            }
            //流媒體初始化
            hCEhomeStream.NET_ESTREAM_Init();
            //設(shè)置HCAapSDKCom組件庫文件夾所在路徑
            HCISUPCMS.BYTE_ARRAY ptrByteArrayCom = new HCISUPCMS.BYTE_ARRAY(256);
            String strPathCom = System.getProperty("user.dir") + "\\lib\\isupsdk\\HCAapSDKCom";      //只支持絕對路徑,建議使用英文路徑
            System.arraycopy(strPathCom.getBytes(), 0, ptrByteArrayCom.byValue, 0, strPathCom.length());
            ptrByteArrayCom.write();
            if (!hCEhomeStream.NET_ESTREAM_SetSDKLocalCfg(5, ptrByteArrayCom.getPointer())) {
                log.info("NET_ESTREAM_SetSDKLocalCfg 5 failed, error:" + hCEhomeStream.NET_ESTREAM_GetLastError());
            }
            hCEhomeStream.NET_ESTREAM_SetLogToFile(3, System.getProperty("user.dir") + "/EHomeSDKLog", false);
        } else if (OsSelect.isLinux()) {
            //設(shè)置libcrypto.so所在路徑
            HCISUPCMS.BYTE_ARRAY ptrByteArrayCrypto = new HCISUPCMS.BYTE_ARRAY(256);
            String strPathCrypto = System.getProperty("user.dir") + "/lib/libcrypto.so"; //Linux版本是libcrypto.so庫文件的路徑
            System.arraycopy(strPathCrypto.getBytes(), 0, ptrByteArrayCrypto.byValue, 0, strPathCrypto.length());
            ptrByteArrayCrypto.write();
            if (!hCEhomeStream.NET_ESTREAM_SetSDKInitCfg(0, ptrByteArrayCrypto.getPointer())) {
                log.info("NET_ESTREAM_SetSDKInitCfg 0 failed, error:" + hCEhomeStream.NET_ESTREAM_GetLastError());
            }
            //設(shè)置libssl.so所在路徑
            HCISUPCMS.BYTE_ARRAY ptrByteArraySsl = new HCISUPCMS.BYTE_ARRAY(256);
            String strPathSsl = System.getProperty("user.dir") + "/lib/libssl.so";    //Linux版本是libssl.so庫文件的路徑
            System.arraycopy(strPathSsl.getBytes(), 0, ptrByteArraySsl.byValue, 0, strPathSsl.length());
            ptrByteArraySsl.write();
            if (!hCEhomeStream.NET_ESTREAM_SetSDKInitCfg(1, ptrByteArraySsl.getPointer())) {
                log.info("NET_ESTREAM_SetSDKInitCfg 1 failed, error:" + hCEhomeStream.NET_ESTREAM_GetLastError());
            }
            hCEhomeStream.NET_ESTREAM_Init();
            //設(shè)置HCAapSDKCom組件庫文件夾所在路徑
            HCISUPCMS.BYTE_ARRAY ptrByteArrayCom = new HCISUPCMS.BYTE_ARRAY(256);
            String strPathCom = System.getProperty("user.dir") + "/lib/HCAapSDKCom/";      //只支持絕對路徑,建議使用英文路徑
            System.arraycopy(strPathCom.getBytes(), 0, ptrByteArrayCom.byValue, 0, strPathCom.length());
            ptrByteArrayCom.write();
            if (!hCEhomeStream.NET_ESTREAM_SetSDKLocalCfg(5, ptrByteArrayCom.getPointer())) {
                log.info("NET_ESTREAM_SetSDKLocalCfg 5 failed, error:" + hCEhomeStream.NET_ESTREAM_GetLastError());
            }
            hCEhomeStream.NET_ESTREAM_SetLogToFile(3, System.getProperty("user.dir") + "/EHomeSDKLog", false);
        }

    }

    public void startRealPlayListen(String smsServerListenIP, String smsServerListenPort) {
        //預(yù)覽監(jiān)聽
        if (fPREVIEW_NEWLINK_CB == null) {
            fPREVIEW_NEWLINK_CB = new FPREVIEW_NEWLINK_CB();
        }
        HCISUPStream.NET_EHOME_LISTEN_PREVIEW_CFG struPreviewListen = new HCISUPStream.NET_EHOME_LISTEN_PREVIEW_CFG();
        System.arraycopy(smsServerListenIP.getBytes(), 0, struPreviewListen.struIPAdress.szIP, 0, smsServerListenIP.length());
        struPreviewListen.struIPAdress.wPort = Short.parseShort(smsServerListenPort); //流媒體服務(wù)器監(jiān)聽端口
        struPreviewListen.fnNewLinkCB = fPREVIEW_NEWLINK_CB; //預(yù)覽連接請求回調(diào)函數(shù)
        struPreviewListen.pUser = null;
        struPreviewListen.byLinkMode = 0; //0- TCP方式,1- UDP方式
        struPreviewListen.write();

        if (StreamHandle < 0) {
            StreamHandle = hCEhomeStream.NET_ESTREAM_StartListenPreview(struPreviewListen);
            if (StreamHandle == -1) {

                System.out.println("NET_ESTREAM_StartListenPreview failed, error code:" + hCEhomeStream.NET_ESTREAM_GetLastError());
                hCEhomeStream.NET_ESTREAM_Fini();
                return;
            } else {
                String StreamListenInfo = new String(struPreviewListen.struIPAdress.szIP).trim() + "_" + struPreviewListen.struIPAdress.wPort;
                System.out.println("流媒體服務(wù):" + StreamListenInfo + ",NET_ESTREAM_StartListenPreview succeed");
            }
        }
    }


    /**
     * 開啟預(yù)覽,
     *
     * @param carId
     * @param lChannel 預(yù)覽通道號
     */
    public void realPlay(int lLoginId, String carId, int lChannel, String smsServerIP, String smsServerPort) throws Exception {
//        JPanelDemo.jRealWinInit();
        HCISUPCMS.NET_EHOME_PREVIEWINFO_IN_V11 struPreviewIn = new HCISUPCMS.NET_EHOME_PREVIEWINFO_IN_V11();
        struPreviewIn.iChannel = lChannel; //通道號
        struPreviewIn.dwLinkMode = 0; //0- TCP方式,1- UDP方式
        struPreviewIn.dwStreamType = 0; //碼流類型:0- 主碼流,1- 子碼流, 2- 第三碼流
        struPreviewIn.struStreamSever.szIP = smsServerIP.getBytes();//流媒體服務(wù)器IP地址,公網(wǎng)地址
        struPreviewIn.struStreamSever.wPort = Short.parseShort(smsServerPort); //流媒體服務(wù)器端口,需要跟服務(wù)器啟動監(jiān)聽端口一致
        struPreviewIn.write();
        //預(yù)覽請求
        HCISUPCMS.NET_EHOME_PREVIEWINFO_OUT struPreviewOut = new HCISUPCMS.NET_EHOME_PREVIEWINFO_OUT();
        boolean getRS = Cms.hCEhomeCMS.NET_ECMS_StartGetRealStreamV11(lLoginId, struPreviewIn, struPreviewOut);
//        boolean getRS = Cms.hCEhomeCMS.NET_ECMS_StartGetRealStream(Cms.lLoginID, struPreviewIn, struPreviewOut);
        //Thread.sleep(10000);
        if (!getRS) {
            log.error("NET_ECMS_StartGetRealStream failed, error code:{}", Cms.hCEhomeCMS.NET_ECMS_GetLastError());
            throw new Exception("攝像頭不存在");
        } else {
            struPreviewOut.read();
            log.info("NET_ECMS_StartGetRealStream succeed, sessionID:{}", struPreviewOut.lSessionID);
            sessionMap.put("session:"+carId+"_"+lChannel,struPreviewOut.lSessionID);
        }
        HCISUPCMS.NET_EHOME_PUSHSTREAM_IN struPushInfoIn = new HCISUPCMS.NET_EHOME_PUSHSTREAM_IN();
        struPushInfoIn.read();
        struPushInfoIn.dwSize = struPushInfoIn.size();
        struPushInfoIn.lSessionID = sessionMap.get("session:"+carId+"_"+lChannel);
        struPushInfoIn.write();
        HCISUPCMS.NET_EHOME_PUSHSTREAM_OUT struPushInfoOut = new HCISUPCMS.NET_EHOME_PUSHSTREAM_OUT();
        struPushInfoOut.read();
        struPushInfoOut.dwSize = struPushInfoOut.size();
        struPushInfoOut.write();
        if (!Cms.hCEhomeCMS.NET_ECMS_StartPushRealStream(lLoginId, struPushInfoIn, struPushInfoOut)) {
            sessionMap.remove("session:"+carId+"_"+lChannel);
            log.error("NET_ECMS_StartPushRealStream failed, error code:" + Cms.hCEhomeCMS.NET_ECMS_GetLastError());
        } else {
            log.info("NET_ECMS_StartPushRealStream succeed, sessionID:" + struPushInfoIn.lSessionID);
        }
    }

    /**
     * 停止預(yù)覽,Stream服務(wù)停止實(shí)時流轉(zhuǎn)發(fā),CMS向設(shè)備發(fā)送停止預(yù)覽請求
     */
    public void StopRealPlay(String carNo, Integer channel) {

        Integer lPreviewHandle = playHandleMap.get("realPlayHandle:" + carNo+channel);
        if (lPreviewHandle == null) {
            return;
        }
        if (!hCEhomeStream.NET_ESTREAM_StopPreview(lPreviewHandle)) {
            System.out.println("NET_ESTREAM_StopPreview failed,err = " + hCEhomeStream.NET_ESTREAM_GetLastError());
            return;
        }

        Integer loginId = Cms.userLoginMap.get(carNo);
        if (loginId == null) {
            return;
        }
        Integer sessionId = sessionMap.get("session:"+carNo+"_"+channel);
        if (sessionId == null) {
            return;
        }

        if (!Cms.hCEhomeCMS.NET_ECMS_StopGetRealStream(loginId, sessionId)) {
            log.info("NET_ECMS_StopGetRealStream failed,err = " + Cms.hCEhomeCMS.NET_ECMS_GetLastError());
            return;
        }
        log.info("停止Stream的實(shí)時流轉(zhuǎn)發(fā)");
        Stream.dataMap.remove(carNo + "_" + channel);
        Stream.sessionMap.remove("session:"+carNo+"_"+channel);
        PipedOutputStream pos = streamMap.get("stream:" + lPreviewHandle);
        if (pos != null) {
            try {
                pos.close();
            } catch (IOException exception) {
                exception.printStackTrace();
            }
            Stream.streamMap.remove("stream:"+ lPreviewHandle);
            Stream.playHandleMap.remove("realPlayHandle:" + carNo+channel);
        }
        log.info("CMS發(fā)送預(yù)覽停止請求");
    }

    /**
     * 播放庫加載
     *
     * @return
     */
    private static boolean CreatePlayInstance() {
        if (playCtrl == null) {
            synchronized (PlayCtrl.class) {
                String strPlayPath = "";
                try {
                    if (OsSelect.isWindows())
                        //win系統(tǒng)加載庫路徑(路徑不要帶中文)
                        strPlayPath = System.getProperty("user.dir") + "\\lib\\isupsdk\\PlayCtrl.dll";
                    else if (OsSelect.isLinux())
                        //Linux系統(tǒng)加載庫路徑(路徑不要帶中文)
                        strPlayPath = System.getProperty("user.dir") + "/lib/libPlayCtrl.so";
                    playCtrl = (PlayCtrl) Native.loadLibrary(strPlayPath, PlayCtrl.class);

                } catch (Exception ex) {
                    log.info("loadLibrary: " + strPlayPath + " Error: " + ex.getMessage());
                    return false;
                }
            }
        }
        return true;
    }

    public void startListenPlayBack(String ip, String port) {
        if (fPLAYBACK_NEWLINK_CB == null) {
            fPLAYBACK_NEWLINK_CB = new PLAYBACK_NEWLINK_CB();
        }
        HCISUPStream.NET_EHOME_PLAYBACK_LISTEN_PARAM param = new HCISUPStream.NET_EHOME_PLAYBACK_LISTEN_PARAM();
        System.arraycopy(ip.getBytes(), 0, param.struIPAdress.szIP, 0, ip.length());
        param.struIPAdress.wPort = Short.parseShort(port);
        param.fnNewLinkCB = fPLAYBACK_NEWLINK_CB;
        param.byLinkMode = 0;//tcp-0;udp-1
        m_lPlayBackListenHandle = hCEhomeStream.NET_ESTREAM_StartListenPlayBack(param);
        if (m_lPlayBackListenHandle < -1) {
            log.info("NET_ESTREAM_StartListenPlayBack failed, error code: {}", hCEhomeStream.NET_ESTREAM_GetLastError());
        } else {
            log.info("回放服務(wù):{}_{}, NET_ESTREAM_StartListenPlayBack success", ip, port);
        }

    }


    public class FPREVIEW_NEWLINK_CB implements HCISUPStream.PREVIEW_NEWLINK_CB {

        @Override
        public boolean invoke(int lLinkHandle, HCISUPStream.NET_EHOME_NEWLINK_CB_MSG pNewLinkCBMsg, Pointer pUserData) throws IOException {
            // 監(jiān)聽,每realPlay調(diào)用時,此方法監(jiān)聽到,開始執(zhí)行
            String userId = new String(pNewLinkCBMsg.szDeviceID).trim();
            int dwChannelNo = pNewLinkCBMsg.dwChannelNo;

            PipedInputStream pis = new PipedInputStream();
            PipedOutputStream pos = new PipedOutputStream();
            Stream.streamMap.put("stream:"+lLinkHandle,pos);
            pos.connect(pis);
            CompletableFuture.runAsync(()-> {
                try {
                    PushUtil.grabAndPushRtmp(pis,"rtmp://"+rtmphost+"/live/"+userId+"_"+ dwChannelNo);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }, Executors.newFixedThreadPool(1));

            log.info("FPREVIEW_NEWLINK_CB callback");
            log.info("FPREVIEW_NEWLINK_CB callback byStreamType : {}", pNewLinkCBMsg.byStreamType);
            //預(yù)覽數(shù)據(jù)回調(diào)參數(shù)
            playHandleMap.put("realPlayHandle:" + userId + dwChannelNo , lLinkHandle );
            HCISUPStream.NET_EHOME_PREVIEW_DATA_CB_PARAM struDataCB = new HCISUPStream.NET_EHOME_PREVIEW_DATA_CB_PARAM();

            FPREVIEW_DATA_CB fPREVIEW_DATA_CB = dataMap.get(userId + "_" + dwChannelNo);
            if (fPREVIEW_DATA_CB == null) {
                fPREVIEW_DATA_CB = new FPREVIEW_DATA_CB(pos);
                dataMap.put(userId + "_" + dwChannelNo,fPREVIEW_DATA_CB);
            }
            struDataCB.fnPreviewDataCB = fPREVIEW_DATA_CB;

            if (!hCEhomeStream.NET_ESTREAM_SetPreviewDataCB(lLinkHandle, struDataCB)) {
                log.info("NET_ESTREAM_SetPreviewDataCB failed err::" + hCEhomeStream.NET_ESTREAM_GetLastError());
                return false;
            }
            return true;
        }
    }

    public class FPREVIEW_DATA_CB implements HCISUPStream.PREVIEW_DATA_CB {

        private PipedOutputStream pos;
        public FPREVIEW_DATA_CB(PipedOutputStream pos) {
            this.pos = pos;
        }

        //實(shí)時流回調(diào)函數(shù)/
        @Override
        public void invoke(int iPreviewHandle, HCISUPStream.NET_EHOME_PREVIEW_CB_MSG pPreviewCBMsg, Pointer pUserData) throws Exception {
//            if (Count == 500) {//降低打印頻率
//                log.info("FPREVIEW_DATA_CB callback, iPreviewHandle:{}", iPreviewHandle);
//                log.info("FPREVIEW_DATA_CB callback, data length:" + pPreviewCBMsg.dwDataLen);
//                Count = 0;
//            }
//            Count++;

            long offset = 0;
            ByteBuffer buffers = pPreviewCBMsg.pRecvdata.getByteBuffer(offset, pPreviewCBMsg.dwDataLen);
            byte[] bytes = new byte[pPreviewCBMsg.dwDataLen];
            buffers.rewind();
            buffers.get(bytes);

            try{
                //2.將數(shù)據(jù)讀入到內(nèi)存空間,此處不可用redis,否則執(zhí)行時間是當(dāng)前10倍
//                PipedOutputStream pos = Stream.streamMap.get("stream:"+iPreviewHandle);
                pos.write(bytes);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    byte[] allEsBytes = null;

    public void writeESH264(final byte[] outputData) throws IOException {
        if (outputData.length <= 0) {
            return;
        }
        if ((outputData[0] & 0xff) == 0x00
                && (outputData[1] & 0xff) == 0x00
                && (outputData[2] & 0xff) == 0x01
                && (outputData[3] & 0xff) == 0xBA) {
            if (allEsBytes != null && allEsBytes.length > 0) {
                return;
//                allEsBytes = null;
            }
        }
        if ((outputData[0] & 0xff) == 0x00
                && (outputData[1] & 0xff) == 0x00
                && (outputData[2] & 0xff) == 0x01
                && (outputData[3] & 0xff) == 0xE0) {
            int from = 9 + outputData[8] & 0xff;
            int len = outputData.length - 9 - (outputData[8] & 0xff);

            byte[] esBytes = new byte[len];
            System.arraycopy(outputData, from, esBytes, 0, len);

            if (allEsBytes == null) {
                allEsBytes = esBytes;
            } else {
                byte[] newEsBytes = new byte[allEsBytes.length + esBytes.length];
                System.arraycopy(allEsBytes, 0, newEsBytes, 0, allEsBytes.length);
                System.arraycopy(esBytes, 0, newEsBytes, allEsBytes.length, esBytes.length);
                allEsBytes = newEsBytes;
            }
        } else {
            allEsBytes = outputData;
        }
    }

    void ffmpegConvetor(String videoInputPath, String videoOutPath) throws Exception {
        if (OsSelect.isWindows()) {
            String ffmpegExe = "E:\\chromeDowload\\ffmpeg.exe";
            List<String> command = new ArrayList<>();
            command.add(ffmpegExe);
            command.add("-i");
            command.add(videoInputPath);
            command.add("-c");
            command.add("copy");
            command.add("-an");
            command.add(videoOutPath);
            ProcessBuilder builder = new ProcessBuilder(command);
            Process process = null;
            try {
                process = builder.start();
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 使用這種方式會在瞬間大量消耗CPU和內(nèi)存等系統(tǒng)資源,所以這里我們需要對流進(jìn)行處理
            try {
                InputStream errorStream = process.getErrorStream();
                InputStreamReader inputStreamReader = new InputStreamReader(errorStream);
                BufferedReader br = new BufferedReader(inputStreamReader);
                String line = "";
                while ((line = br.readLine()) != null) {
                }
                if (br != null) {
                    br.close();
                }
                if (inputStreamReader != null) {
                    inputStreamReader.close();
                }
                if (errorStream != null) {
                    errorStream.close();
                }
            } catch (NullPointerException e) {
                e.printStackTrace();
            }
        } else if (OsSelect.isLinux()) {
            //todo linux的ffmpeg使用
        }
    }


    public static class PLAYBACK_NEWLINK_CB implements HCISUPStream.PLAYBACK_NEWLINK_CB {
        @Override
        public boolean invoke(int lPlayBackLinkHandle, HCISUPStream.NET_EHOME_PLAYBACK_NEWLINK_CB_INFO pNewLinkCBInfo, Pointer pUserData) {
            pNewLinkCBInfo.read();
            log.info("PLAYBACK_NEWLINK_CB callback, szDeviceID:" + new String(pNewLinkCBInfo.szDeviceID).trim()
                    + ",lSessionID:" + pNewLinkCBInfo.lSessionID + ",dwChannelNo:" + pNewLinkCBInfo.dwChannelNo);
            m_lPlayBackLinkHandle = lPlayBackLinkHandle;
            HCISUPStream.NET_EHOME_PLAYBACK_DATA_CB_PARAM struCBParam = new HCISUPStream.NET_EHOME_PLAYBACK_DATA_CB_PARAM();
            //預(yù)覽數(shù)據(jù)回調(diào)參數(shù)
            if (fPLAYBACK_DATA_CB == null) {
                fPLAYBACK_DATA_CB = new PLAYBACK_DATA_CB();
            }
//            pNewLinkCBInfo.fnPlayBackDataCB = fPLAYBACK_DATA_CB;
//            pNewLinkCBInfo.byStreamFormat = 0;
            struCBParam.fnPlayBackDataCB = fPLAYBACK_DATA_CB;
            struCBParam.byStreamFormat = 0;
            struCBParam.write();
//            pNewLinkCBInfo.write();
            if (!hCEhomeStream.NET_ESTREAM_SetPlayBackDataCB(lPlayBackLinkHandle, struCBParam)) {
                log.info("NET_ESTREAM_SetPlayBackDataCB failed");
            }
            return true;
        }
    }

    public static class PLAYBACK_DATA_CB implements HCISUPStream.PLAYBACK_DATA_CB {
        //實(shí)時流回調(diào)函數(shù)
        @Override
        public boolean invoke(int iPlayBackLinkHandle, HCISUPStream.NET_EHOME_PLAYBACK_DATA_CB_INFO pDataCBInfo, Pointer pUserData) {
            if (iCount == 500) {//降低打印頻率
                log.info("PLAYBACK_DATA_CB callback , dwDataLen:" + pDataCBInfo.dwDataLen + ",dwType:" + pDataCBInfo.dwType);
                iCount = 0;
            }
            iCount++;
            //播放庫SDK解碼顯示在win窗口上,
            switch (pDataCBInfo.dwType) {
                case HCNetSDK.NET_DVR_SYSHEAD: //系統(tǒng)頭
//                    boolean b_port = playCtrl.PlayM4_GetPort(m_lPort);
//                    if (b_port == false) //獲取播放庫未使用的通道號
//                    {
//                        break;
//                    }
//                    if (pDataCBInfo.dwDataLen > 0) {
//                        if (!playCtrl.PlayM4_SetOverlayMode(m_lPort.getValue(), false, 0)) {
//                            break;
//                        }
//
//                        if (!playCtrl.PlayM4_SetStreamOpenMode(m_lPort.getValue(), PlayCtrl.STREAME_FILE))  //設(shè)置文件流播放模式
//                        {
//                            break;
//                        }
//
//                        if (!playCtrl.PlayM4_OpenStream(m_lPort.getValue(), pDataCBInfo.pData, pDataCBInfo.dwDataLen, 2 * 1024 * 1024)) //打開流接口
//                        {
//                            break;
//                        }
//                        W32API.HWND hwnd = new W32API.HWND(Native.getComponentPointer(IsupTest.panelRealplay));
//                        if (!playCtrl.PlayM4_Play(m_lPort.getValue(), hwnd)) //播放開始
//                        {
//                            break;
//                        }
//                    }
                case HCNetSDK.NET_DVR_STREAMDATA:   //碼流數(shù)據(jù)
                    if (pDataCBInfo.dwDataLen > 0) {
//                        for (int i = 0; i < 1000; i++) {
//                            boolean bRet = playCtrl.PlayM4_InputData(m_lPort.getValue(), pDataCBInfo.pData, pDataCBInfo.dwDataLen);
//                            if (!bRet) {
//                                if (i >= 999) {
//                                    log.info("PlayM4_InputData,failed err:" + playCtrl.PlayM4_GetLastError(m_lPort.getValue()));
//                                }
//                                try {
//                                    Thread.sleep(1000);
//                                } catch (InterruptedException e) {
//                                    e.printStackTrace();
//                                }
//                            } else {
//                                break;
//                            }
//                        }
                        try {
                            String fileName = redisUtil.get("downloadHandle:" + iPlayBackLinkHandle);
                            FileOutputStream m_file = new FileOutputStream(fileName, true);
                            long offset = 0;
                            ByteBuffer buffers = pDataCBInfo.pData.getByteBuffer(offset, pDataCBInfo.dwDataLen);
                            byte[] bytes = new byte[pDataCBInfo.dwDataLen];
                            buffers.rewind();
                            buffers.get(bytes);
                            m_file.write(bytes);
                            m_file.close();
//                           if (pDataCBInfo.dwDataLen < 1024)
//                                VideoUtil.convetor(fileName, fileName + ".mp4");

                        } catch (FileNotFoundException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        } catch (IOException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    break;
                //如果僅需保存回放的視頻流文件,參考一下注釋的代碼
			/*try {

				m_file = new FileOutputStream(file, true);
				long offset = 0;
	             ByteBuffer buffers = pDataCBInfo.pData.getByteBuffer(offset, pDataCBInfo.dwDataLen);
	             byte [] bytes = new byte[pDataCBInfo.dwDataLen];
	             buffers.rewind();
	             buffers.get(bytes);
	             m_file.write(bytes);
	             m_file.close();
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}*/
                case 3: //結(jié)束
                    String fileName = redisUtil.get("downloadHandle:" + iPlayBackLinkHandle);
                    try {
                        if (OsSelect.isLinux()) {
                            convetorLinux(fileName, fileName + ".mp4");
                        } else {
                            convetorWindows(fileName, fileName + ".mp4");
                        }
                        break;
                    }catch (Exception ex) {
                        ex.printStackTrace();
                    }
            }
            return true;
        }
    }

    public static void convetorWindows(String videoInputPath, String videoOutPath) throws Exception{
        String ffmpegExe = "E:\\software\\ffmpeg-5.0.1-essentials_build\\bin\\ffmpeg.exe";
        List<String> command = new ArrayList<>();
        command.add(ffmpegExe);
        command.add("-i");
        command.add(videoInputPath);
        command.add("-c");
        command.add("copy");
        command.add("-an");
        command.add(videoOutPath);
        ProcessBuilder builder = new ProcessBuilder(command);
        Process process = null;
        try {
            process = builder.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 使用這種方式會在瞬間大量消耗CPU和內(nèi)存等系統(tǒng)資源,所以這里我們需要對流進(jìn)行處理
        try {
            InputStream errorStream = process.getErrorStream();
            InputStreamReader inputStreamReader = new InputStreamReader(errorStream);
            BufferedReader br = new BufferedReader(inputStreamReader);
            String line = "";
            while ((line = br.readLine()) != null) {
            }
            if (br != null) {
                br.close();
            }
            if (inputStreamReader != null) {
                inputStreamReader.close();
            }
            if (errorStream != null) {
                errorStream.close();
            }
            Path p = Paths.get(videoInputPath);
            Files.delete(p);
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
    }

    public static void convetorLinux(String videoInputPath, String videoOutPath) throws Exception {
        String ffmpegExe = "/usr/local/ffmpeg/bin/ffmpeg";
        String videoCommend = ffmpegExe + " -i " +  videoInputPath + " -c copy -an "  + videoOutPath;
        try {
            Runtime rt = Runtime.getRuntime();
            Process proc = rt.exec(videoCommend);
            InputStream stderr = proc.getErrorStream();
            InputStreamReader isr = new InputStreamReader(stderr);
            BufferedReader br = new BufferedReader(isr);
            String line = null;
            while ((line = br.readLine()) != null){
            }
            if (br != null) {
                br.close();
            }
            if (isr != null) {
                isr.close();
            }
            if (stderr != null) {
                stderr.close();
            }
            int exitVal = proc.waitFor();
            Path p = Paths.get(videoInputPath);
            Files.delete(p);
        } catch (Throwable t) {
            t.printStackTrace();
        }

    }


}



到了這里,關(guān)于web實(shí)時預(yù)覽功能開發(fā) java 海康sdk nvr的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • ??祵?shí)時監(jiān)控預(yù)覽視頻流接入web

    海康實(shí)時監(jiān)控預(yù)覽視頻流接入web

    ? ? ? ? 我們采取的方案是后端獲取視頻流返回給前端,然后前端播放 根據(jù)官方文檔傳輸對應(yīng)的參數(shù)? 官方接口限制:為保證數(shù)據(jù)的安全性,取流URL設(shè)有有效時間,有效時間為5分鐘。 注意不同協(xié)議的限制不同,rtsp沒得限制但前端播放麻煩,web端展示的話ws比較好 ??甸_放平

    2024年04月17日
    瀏覽(26)
  • vue3實(shí)現(xiàn)??低暩鶕?jù)??挡寮M(jìn)行監(jiān)控實(shí)時預(yù)覽和回放功能

    因?yàn)槲业奈恼乱呀?jīng)寫過基于vue實(shí)現(xiàn)海康web插件進(jìn)行視頻播放開箱即用文章,這個文章是利用 vite+vue3+js 進(jìn)行編寫的,大致內(nèi)容跟vue2一樣,拿過去能直接用。 至于我為什么要用js而不用ts,因?yàn)楹?堤峁┑娜齻€腳本為js語言的,ts嘗試過一次,我道行太淺,沒搞明白。 這些代碼是

    2024年02月05日
    瀏覽(127)
  • vue2實(shí)現(xiàn)??低暩鶕?jù)??挡寮M(jìn)行監(jiān)控實(shí)時預(yù)覽和回放功能,全套代碼,開箱即用。

    vue2實(shí)現(xiàn)??低暩鶕?jù)??挡寮M(jìn)行監(jiān)控實(shí)時預(yù)覽和回放功能,全套代碼,開箱即用。

    ?這是一套拿到手就能直接用的根據(jù)??堤峁┑臄z像機(jī)節(jié)點(diǎn)實(shí)時預(yù)覽和回放的全步驟代碼,開箱即用。 ?我的是基于vue2寫的,vue3可以看我下一篇文章。 很多人在開發(fā)vue項(xiàng)目的時候,不知道怎么去開發(fā)視頻實(shí)時預(yù)覽和回放功能,然后一直查文檔,再去看別人寫的項(xiàng)目,就是無

    2023年04月15日
    瀏覽(23)
  • JavaCV音視頻開發(fā)寶典:使用JavaCV讀取海康平臺或??稻W(wǎng)絡(luò)攝像頭sdk回調(diào)視頻TS碼流并解析預(yù)覽圖像

    JavaCV音視頻開發(fā)寶典:使用JavaCV讀取??灯脚_或??稻W(wǎng)絡(luò)攝像頭sdk回調(diào)視頻TS碼流并解析預(yù)覽圖像

    《JavaCV音視頻開發(fā)寶典》專欄目錄導(dǎo)航 《JavaCV音視頻開發(fā)寶典》專欄介紹和目錄 ? 兩年前博主寫了如何利用JavaCV解析各種h264裸流,《JavaCV音視頻開發(fā)寶典:使用javacv讀取GB28181、??荡笕A平臺和網(wǎng)絡(luò)攝像頭sdk回調(diào)視頻碼流并解析預(yù)覽圖像》,但是隨著時間變化,各個廠商s

    2024年02月14日
    瀏覽(24)
  • 記錄對接??低晹z像頭web端實(shí)時預(yù)覽:Linux+ffmpeg+nginx轉(zhuǎn)換RTSP視頻流(完整版實(shí)現(xiàn))

    ????????需求:web端實(shí)現(xiàn)海康攝像頭實(shí)時預(yù)覽效果 ????????由于市面上大部分網(wǎng)絡(luò)攝像頭都支持RTSP協(xié)議視頻流,web端一般無法直接使用RTSP實(shí)現(xiàn)視頻預(yù)覽,本篇使用ffmpeg對視頻流進(jìn)行轉(zhuǎn)換,最終實(shí)現(xiàn)web端實(shí)時預(yù)覽。 ????????工具介紹:ffmpeg、nginx、vue ????????介

    2024年01月25日
    瀏覽(25)
  • JavaCV音視頻開發(fā)寶典:使用JavaCV讀取海康平臺或??稻W(wǎng)絡(luò)攝像頭sdk回調(diào)錄像回放視頻PS碼流并解析預(yù)覽圖像

    JavaCV音視頻開發(fā)寶典:使用JavaCV讀取??灯脚_或??稻W(wǎng)絡(luò)攝像頭sdk回調(diào)錄像回放視頻PS碼流并解析預(yù)覽圖像

    《JavaCV音視頻開發(fā)寶典》專欄目錄導(dǎo)航 《JavaCV音視頻開發(fā)寶典》專欄介紹和目錄 ? 上一章中《JavaCV音視頻開發(fā)寶典:使用JavaCV讀取??灯脚_或海康網(wǎng)絡(luò)攝像頭sdk回調(diào)視頻TS流并解析預(yù)覽圖像》已經(jīng)詳細(xì)介紹了針對??礢DK實(shí)時視頻流回調(diào)的TS流解析實(shí)現(xiàn),并且也提到了PS流和

    2024年02月16日
    瀏覽(24)
  • ??低晹z像頭二次開發(fā)_云臺控制_視頻畫面實(shí)時預(yù)覽(基于Qt實(shí)現(xiàn))

    ??低晹z像頭二次開發(fā)_云臺控制_視頻畫面實(shí)時預(yù)覽(基于Qt實(shí)現(xiàn))

    需求:需要在公司的產(chǎn)品里集成??低晹z像頭的SDK,用于控制??低暤臄z像頭。 拍照抓圖、視頻錄制、云臺控制、視頻實(shí)時預(yù)覽等等功能。 開發(fā)環(huán)境: windows-X64(系統(tǒng)) + Qt5.12.6(Qt版本) + MSVC2017_X64(使用的編譯器) ??低曁峁┝?設(shè)備網(wǎng)絡(luò)SDK ,設(shè)備網(wǎng)絡(luò)SDK是基于設(shè)備私有網(wǎng)

    2024年02月13日
    瀏覽(23)
  • 通過java解碼web前端直接預(yù)覽??低晹z像頭

    通過java解碼web前端直接預(yù)覽??低晹z像頭

    ? ? ? ? 最近進(jìn)行項(xiàng)目開發(fā)時遇到了需要前端直接調(diào)用攝像頭,并直接進(jìn)行播放的需求。原本計(jì)劃通過??低暪倬W(wǎng)的《WEB無插件開發(fā)包 V3.2》直接進(jìn)行控制、交互,實(shí)現(xiàn)攝像頭直接登錄以及取流預(yù)覽。但是前端人員現(xiàn)場駐場開發(fā)后反映各種兼容性問題頻發(fā),反正就是不能友

    2024年02月01日
    瀏覽(20)
  • ??低曄鄼C(jī)SDK二次開發(fā)(JAVA語言)

    ??低曄鄼C(jī)SDK二次開發(fā)(JAVA語言)

    前言 有個項(xiàng)目需要使用java程序讀取??低暤南鄼C(jī)圖片。相機(jī)通過以太網(wǎng)連接服務(wù)器,部署在服務(wù)器上的java程序?qū)⑾鄼C(jī)拍攝的畫面保存在指定路徑下。 ??低曁峁┝藄dk開發(fā)包,可以在官網(wǎng)中下載,windows和linux系統(tǒng)都有。但是開發(fā)包中給出的示例代碼,無法滿足實(shí)際需要,

    2024年04月29日
    瀏覽(25)
  • ??礧EB3.3控件開發(fā)包 V3.3 前端vue項(xiàng)目調(diào)用實(shí)時監(jiān)控畫面

    ??礧EB3.3控件開發(fā)包 V3.3 前端vue項(xiàng)目調(diào)用實(shí)時監(jiān)控畫面

    公司業(yè)務(wù)迭代, 需要前端vue項(xiàng)目里增加一個查看實(shí)時監(jiān)控模塊, 這個需求是之前離職的前端小哥沒有研究明白的, 現(xiàn)在落在了我的肩上, 壓力還是有的. 但是壓力歸壓力, 問題還是要解決的. 第一步: 調(diào)研大佬們已經(jīng)實(shí)現(xiàn)的方案, 找設(shè)備對接. 公司后端大佬提出用官方SDK稍加修改即

    2024年02月08日
    瀏覽(22)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包