Java 海康錄像機(NVR&&DVR)二次開發-通過時間下載錄像和抓圖功能

海康錄像機還是國內市場比較火的錄像機吧!反正我也不知道,我也不敢問啊!╮(︶﹏︶)╭話不多說!趕緊去海康官網選擇一個相應sdk開放包下載,這裏給老鐵們奉上地址:盤他⁽⁽ƪ(•̩̩̩̩_•̩̩̩̩)ʃ⁾⁾ᵒᵐᵍᵎᵎ

第一步:海康官網提供的開發文檔和操作手冊是c++版本,我一個學過c++都看得不是很懂,可能是我比較菜吧!如果你沒學過的話,可能會你會比較~%?…;# *’☆&℃$︿★? 亂碼!好吧,我來介紹java如何使用,看下圖,這是我從官網下載的sdk,你需要把依賴jar包導入到項目中,我使用maven導入的依賴

<!--海康錄像機二次開發依賴jar包-->
<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna</artifactId>
    <version>3.0.9</version>
</dependency>
<!--海康錄像機sdk官方提供jar包-->
<dependency>
    <groupId>com.qy</groupId>
    <artifactId>examples</artifactId><!--需要在maven自行安裝這個jar包-->
    <version>1.0.0</version>
</dependency>

第二步:修改程序代碼,我們找到官方提供的sdk,找到java示例代碼,在下圖第一張圖所示所顯示路徑中找到HCNetSDK.java導入項目當中,把海康sdk中庫文件裏的HCNetSDK.dll、HCCore.dll、PlayCtrl.dll、SuperRender.dll、HCNetSDKCom文件夾等文件均拷貝到本地路徑。HCNetSDKCom文件夾(包含裏面的功能組件dll庫文件)需要和HCNetSDK.dll、HCCore.dll一起加載,放在同一個目錄下,且HCNetSDKCom文件夾名不能修改。把HCNetSDK.java文件複製一份到本地路徑,如下圖第二張圖所示。其中HCNetSDK.java文件自己指定loadlibrary加載庫的路徑,如下圖第三張圖所示。

第三步:這一步對抓圖功能很關鍵,我們要修改HCNetSDK.java裏面的內容(修改之後要保證和本地磁盤下HCNetSDK.java文件一致,複製過去就可以了),把sJpegPicBuffer的String類型改成ByteBuffer就可以了

第四步:開始編碼通過時間下載錄像這個功能,通過時間下載功能測試在play類的main方法中

public class VideoDowload {
    private static Logger logger = LoggerFactory.getLogger(VideoDowload.class);
    private static HCNetSDK hcNetSDK = HCNetSDK.INSTANCE;
    private NativeLong userId;//用戶句柄
    private NativeLong loadHandle;//下載句柄
    private Timer downloadTimer;

    /**
     *按時間下載視頻
     * @param dvr
     * @param startTime
     * @param endTime
     * @param filePath
     * @param channel
     * @return
     */
    public boolean downloadVideo(Dvr dvr,Date startTime, Date endTime, String filePath, int channel) {
        boolean initFlag = hcNetSDK.NET_DVR_Init();
        if(!initFlag) { //返回值爲布爾值 fasle初始化失敗
            logger.warn("hksdk(視頻)-海康sdk初始化失敗!");
            return false;
        }
        HCNetSDK.NET_DVR_DEVICEINFO_V30 deviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V30();
        userId = hcNetSDK.NET_DVR_Login_V30(dvr.getDvrip(),(short)dvr.getDvrport(),dvr.getDvrusername(),dvr.getDvrpassword(),deviceInfo);
        logger.info("hksdk(視頻)-登錄海康錄像機信息,狀態值:"+hcNetSDK.NET_DVR_GetLastError());
        long lUserId = userId.longValue();
        if(lUserId==-1) {
            logger.warn("hksdk(視頻)-海康sdk登錄失敗!");
            return false;
        }
        loadHandle =new NativeLong(-1);
        if(loadHandle.intValue()==-1) {
            loadHandle = hcNetSDK.NET_DVR_GetFileByTime(userId,new NativeLong(channel),getHkTime(startTime),getHkTime(endTime),filePath);
            logger.info("hksdk(視頻)-獲取播放句柄信息,狀態值:"+hcNetSDK.NET_DVR_GetLastError());
            if(loadHandle.intValue()>=0) {
                boolean downloadFlag = hcNetSDK.NET_DVR_PlayBackControl(loadHandle,hcNetSDK.NET_DVR_PLAYSTART,0,null);
                int tmp = -1;
                IntByReference pos = new IntByReference();
                while(true) {
                    boolean backFlag = hcNetSDK.NET_DVR_PlayBackControl(loadHandle,hcNetSDK.NET_DVR_PLAYGETPOS,0,pos);
                    if(!backFlag) {//防止單個線程死循環
                        return downloadFlag;
                    }
                    int produce =pos.getValue();
                    if((produce%10)==0&&tmp!=produce) {//輸出進度
                        tmp = produce;
                        logger.info("hksdk(視頻)-視頻下載進度:"+"=="+produce+"%");
                    }
                    if(produce ==100) {//下載成功
                        hcNetSDK.NET_DVR_StopGetFile(loadHandle);
                        loadHandle.setValue(-1);
                        hcNetSDK.NET_DVR_Logout(userId);//退出錄像機
                        logger.info("hksdk(視頻)-退出狀態"+hcNetSDK.NET_DVR_GetLastError());
                        //hcNetSDK.NET_DVR_Cleanup();
                        return true;
                    }
                    if(produce>100) {//下載失敗
                        hcNetSDK.NET_DVR_StopGetFile(loadHandle);
                        loadHandle.setValue(-1);
                        logger.warn("hksdk(視頻)-海康sdk由於網絡原因或DVR忙,下載異常終止!錯誤原因:"+ hcNetSDK.NET_DVR_GetLastError());
                        //hcNetSDK.NET_DVR_Logout(userId);//退出錄像機
                        //logger.info("hksdk(視頻)-退出狀態"+hcNetSDK.NET_DVR_GetLastError());
                        return false;
                    }
                }
            }else{
                System.out.println("hksdk(視頻)-下載失敗" + hcNetSDK.NET_DVR_GetLastError());
                return false;
            }
        }
        return false;
    }

    /**
     * 獲取海康錄像機格式的時間
     * @param time
     * @return
     */
    public HCNetSDK.NET_DVR_TIME getHkTime(Date time) {
        HCNetSDK.NET_DVR_TIME structTime = new HCNetSDK.NET_DVR_TIME();
        String str = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(time);
        String[] times = str.split("-");
        structTime.dwYear = Integer.parseInt(times[0]);
        structTime.dwMonth = Integer.parseInt(times[1]);
        structTime.dwDay = Integer.parseInt(times[2]);
        structTime.dwHour = Integer.parseInt(times[3]);
        structTime.dwMinute =Integer.parseInt(times[4]);
        structTime.dwSecond = Integer.parseInt(times[5]);
        return structTime;
    }

    public static void main(String[] args) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        Date startTime =null;
        Date endTime = null;
        try {
            startTime = sdf.parse("20190712164200");   //開始時間
            endTime =   sdf.parse("20190712170000");      //結束時間
        } catch (ParseException e) {
            e.printStackTrace();
        }
        VideoDowload test = new VideoDowload();
        Dvr dvr = new Dvr(0,"錄像機ip",8000,"錄像機用戶名","錄像機密碼",null,0);
        int channel =2//通道
        System.out.print(test.downloadVideo(dvr,startTime,endTime,"G:\\test\\test.mp4",chanel));
    }
}

第四步:開始編碼抓圖功能,抓圖功能測試在Camera的main方法裏面。

public class Camera {
    private static  HCNetSDK hcNetSDK = HCNetSDK.INSTANCE;
    private Logger logger = LoggerFactory.getLogger(Camera.class);
    private NativeLong userId;//用戶句柄

    /**
     * 抓拍圖片
     * @param dvr
     */
    public void getDVRPic(Dvr dvr, int chan, String imgpath) {
        NativeLong chanLong = new NativeLong(chan);

        if(!hcNetSDK.NET_DVR_Init()) {
            logger.warn("hksdk(抓圖)-海康sdk初始化失敗!");
            return ;
        }
        HCNetSDK.NET_DVR_DEVICEINFO_V30 devinfo = new HCNetSDK.NET_DVR_DEVICEINFO_V30();// 設備信息
        //註冊設備
        userId = hcNetSDK.NET_DVR_Login_V30(dvr.getDvrip(),(short)dvr.getDvrport(),dvr.getDvrusername(), dvr.getDvrpassword(), devinfo);// 返回一個用戶編號,同時將設備信息寫入devinfo

        if (userId.intValue() < 0) {
            logger.warn("hksdk(抓圖)-設備註冊失敗,錯誤碼:"+hcNetSDK.NET_DVR_GetLastError());
            return;
        }
        HCNetSDK.NET_DVR_WORKSTATE_V30 devwork = new HCNetSDK.NET_DVR_WORKSTATE_V30();
        if (!hcNetSDK.NET_DVR_GetDVRWorkState_V30(userId, devwork)) {
            // 返回Boolean值,判斷是否獲取設備能力
            logger.info("hksdk(抓圖)-返回設備狀態失敗");
        }
        //圖片質量
        HCNetSDK.NET_DVR_JPEGPARA jpeg = new HCNetSDK.NET_DVR_JPEGPARA();
        //設置圖片分辨率
        jpeg.wPicSize=5;
        //設置圖片質量
        jpeg.wPicQuality=0;
        IntByReference a = new IntByReference();
        //設置圖片大小
        ByteBuffer jpegBuffer = ByteBuffer.allocate(1024 * 1024);
        //String jpegBuffer ="1024 * 1024";
        File file = new File(imgpath);
        // 抓圖到內存,單幀數據捕獲並保存成JPEG存放在指定的內存空間中
        //需要加入通道
        boolean is = hcNetSDK.NET_DVR_CaptureJPEGPicture_NEW(userId, chanLong, jpeg, jpegBuffer, 1024 * 1024, a);
        if(is) {
            logger.info("hksdk(抓圖)-結果狀態值(0表示成功):"+hcNetSDK.NET_DVR_GetLastError());
            //存儲到本地
            BufferedOutputStream outputStream = null;
            try {
                outputStream = new BufferedOutputStream(new FileOutputStream(file));
                outputStream.write(jpegBuffer.array(),0,a.getValue());
                outputStream.flush();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally{
                if(outputStream!=null) {
                    try {
                        outputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }else{
            logger.info("hksdk(抓圖)-抓取失敗,錯誤碼:"+hcNetSDK.NET_DVR_GetLastError());
        }

        hcNetSDK.NET_DVR_Logout(userId);//退出登錄
        //hcNetSDK.NET_DVR_Cleanup();
    }
    public static void main(String[] args) {
        Camera camera = new Camera();
        Dvr dvr = new Dvr(0,"錄像機ip",8000,"錄像機用戶名","密碼",null,0);
        String imgpath ="G:\\test\\test.jpg";
        int channel = 2;//通道號
        camera.getDVRPic(dvr,channel,imgpath);
    }
}

注意:Dvr類就是錄像機設備信息類,你自己建一個你自己的就可以了,海康錄像機每一個攝像槍對應一個通道號,在通道號上選擇,我這裏選擇通道號是1,2......。但是你可能會選擇錯誤,有些錄像機實際通道號是從33開始的,對應錄像機設置通道1、通道2......,可能不同的錄像機不太一樣吧!

如果需要實現其他功能,各位老鐵去看喪心病狂的c++文檔吧!或許可以幫到你。

▄█▀█●各位老鐵,如果我的代碼能夠幫助到你,請給我一個贊吧!有啥子不懂的地方或者開發與遇到啥問題請評論。懂就給你解答。不懂的話,我也沒辦法啊!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章