Linux和Windows下集成海康攝像頭(特別解決linux加載不到庫)


問題

最近要集成海康攝像頭部署到linux服務器,但是一直調用不到so文件,所以記錄下解決過程,
由於自己不熟悉jna,所以請輕噴,Stay Hungry,Stay Foolish.

海康sdk官方下載地址

前期准備

至於為什么先講linux等下就知道了,linux的sdk下載下來目錄如下:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Ra7VlK6d-1590658348978)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200528163929984.png)]

開發文檔有自己的業務需求就看對應的開放文檔

我們直接看LinuxJavaDemo文件夾

在這里插入圖片描述

這邊我選擇的是方法一,但是不是在系統的/usr/lib文件下,自己新建的文件夾

linux准備工作

  1. linux下搭配jdk1.8,我這邊linux服務器新建了一個目錄(/home/opt/hcnet)來存放下面的so文件

  2. 上傳文件到linux目錄下 就是圖中的lib文件,所有的都上傳到你的linux目錄

在這里插入圖片描述

  1. 創建lib文件夾引入sdk包中的examples.jar和jna.jar
    在這里插入圖片描述
    在pom中添加 不然會報錯

    <dependency>
                <groupid>com.sun.jna</groupid>
                <artifactid>yx</artifactid>
                <version>0.0.1</version>
                <scope>system</scope>
                <systempath>${project.basedir}/lib/jna.jar</systempath>
            </dependency>
            <dependency>
                <groupid>com.sun.jna.examples</groupid>
                <artifactid>yx</artifactid>
                <version>0.0.1</version>
                <scope>system</scope>
                <systempath>${project.basedir}/lib/examples.jar</systempath>
            </dependency>
    

    打包添加如下配置
    在這里插入圖片描述

  2. 開始集成

    將linux中的HCNetSDK.java放到項目中,修改代碼,將他初始化的地方注釋掉,我們自己初始化

在這里插入圖片描述
下面就是自己的初始化代碼

package com.yx.hkdemo.config;

import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.Platform;
import com.yx.hkdemo.HCNetSDK;

import java.io.File;

/**
 * @author :tangfan
 * @date :Created in 2020/5/25 17:36
 * @description:
 * @modified By:
 */
public class GetHCNetSdk {
    public static HCNetSDK hcNetSDK = null;
    //windows下的路徑
    String PATH_WIN = System.getProperty("user.dir") + File.separator + "hkwinlib" + File.separator + "HCNetSDK";
    String PATH_LINUX = "/home/opt/hcnet/libhcnetsdk.so";
    private HCNetSDK.NET_DVR_DEVICEINFO_V30 deviceInfo;//設備信息
    private NativeLong lUserID;//用戶句柄
    private NativeLong lAlarmHandle;//報警布防句柄
    //    private HCNetSDK.FMSGCallBack_V31 fMSFCallBack_V31;//報警回調函數實現
    private HCNetSDK.FMSGCallBack fMSFCallBack;//報警回調函數實現
    private String deviceIP;//已登錄設備的IP地址
    private int devicePort;//設備端口號
    private String username;//設備用戶名
    private String password;//設備登陸密碼
    private boolean init_flag;//初始化識別標志
    private boolean reg_flag;//設備注冊識別標志

    public GetHCNetSdk() {
        install();
    }

    private void install() {
        if (Platform.isWindows()) {
            hcNetSDK = (HCNetSDK) Native.loadLibrary(PATH_WIN, HCNetSDK.class);
            
        }
        if (Platform.isLinux()) {
            hcNetSDK = (HCNetSDK) Native.loadLibrary(PATH_LINUX, HCNetSDK.class);
           
        }
    }
}

如果在linux上運行報錯,請在linux下的hcNetSDK = (HCNetSDK) Native.loadLibrary(PATH_LINUX, HCNetSDK.class);后面加入官方的這段代碼,並且修改成自己的路徑,我的是/home/opt/hcnet
在這里插入圖片描述
代碼在下面:

  //設置HCNetSDKCom組件庫所在路徑
//        /home/opt/hcnet/libhcnetsdk.so
//        /home/opt/hcnet
            String strPathCom = "/home/opt/hcnet";
            HCNetSDK.NET_DVR_LOCAL_SDK_PATH struComPath = new HCNetSDK.NET_DVR_LOCAL_SDK_PATH();
            System.arraycopy(strPathCom.getBytes(), 0, struComPath.sPath, 0, strPathCom.length());
            struComPath.write();
            hcNetSDK.NET_DVR_SetSDKInitCfg(2, struComPath.getPointer());

//設置libcrypto.so所在路徑
            HCNetSDK.BYTE_ARRAY ptrByteArrayCrypto = new HCNetSDK.BYTE_ARRAY(256);
            String strPathCrypto = "/home/opt/hcnet/libcrypto.so";
            System.arraycopy(strPathCrypto.getBytes(), 0, ptrByteArrayCrypto.byValue, 0, strPathCrypto.length());
            ptrByteArrayCrypto.write();
            hcNetSDK.NET_DVR_SetSDKInitCfg(3, ptrByteArrayCrypto.getPointer());

//設置libssl.so所在路徑
            HCNetSDK.BYTE_ARRAY ptrByteArraySsl = new HCNetSDK.BYTE_ARRAY(256);
            String strPathSsl = "/home/opt/hcnet/libssl.so";
            System.arraycopy(strPathSsl.getBytes(), 0, ptrByteArraySsl.byValue, 0, strPathSsl.length());
            ptrByteArraySsl.write();
            hcNetSDK.NET_DVR_SetSDKInitCfg(4, ptrByteArraySsl.getPointer());
  1. 編寫工具類,自己寫方法
package com.yx.hkdemo;

import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.NativeLongByReference;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.swing.*;

//import org.apache.commons.lang.StringUtils;

//import cc.eguid.FFmpegCommandManager.FFmpegManager;
//import cc.eguid.FFmpegCommandManager.FFmpegManagerImpl;
//import com.dfzx.common.util.CommonKit;
@Data
@AllArgsConstructor
public class HCNetTools {
    HCNetSDK hCNetSDK = null;
    HCNetSDK.NET_DVR_DEVICEINFO_V30 m_strDeviceInfo;//設備信息
    HCNetSDK.NET_DVR_IPPARACFG m_strIpparaCfg;//IP參數
    HCNetSDK.NET_DVR_CLIENTINFO m_strClientInfo;//用戶參數
    boolean bRealPlay;//是否在預覽.
    String m_sDeviceIP;//已登錄設備的IP地址
    NativeLong lUserID;//用戶句柄
    NativeLong lPreviewHandle;//預覽句柄
    NativeLongByReference m_lPort;//回調預覽時播放庫端口指針

    public HCNetTools(HCNetSDK sdk) {
        JPopupMenu.setDefaultLightWeightPopupEnabled(false);//防止被播放窗口(AWT組件)覆蓋
        lUserID = new NativeLong(-1);
        lPreviewHandle = new NativeLong(-1);
        m_lPort = new NativeLongByReference(new NativeLong(-1));
        this.hCNetSDK = sdk;
    }


//    FFmpegManager manager;//rstp轉rmtp工具


    //FRealDataCallBack fRealDataCallBack;//預覽回調函數實現

    public HCNetTools() {
        JPopupMenu.setDefaultLightWeightPopupEnabled(false);//防止被播放窗口(AWT組件)覆蓋
        lUserID = new NativeLong(-1);
        lPreviewHandle = new NativeLong(-1);
        m_lPort = new NativeLongByReference(new NativeLong(-1));
        //fRealDataCallBack= new FRealDataCallBack();
    }

    /**
     * 初始化資源配置
     */
    public int initDevices() {
        if (!hCNetSDK.NET_DVR_Init()) return 1;//初始化失敗
        return 0;
    }

    /**
     * 設備注冊
     *
     * @param name     設備用戶名
     * @param password 設備登錄密碼
     * @param ip       IP地址
     * @param port     端口
     * @return 結果
     */
    public int deviceRegist(String name, String password, String ip, String port) {
        if (bRealPlay) {//判斷當前是否在預覽
            return 2;//"注冊新用戶請先停止當前預覽";
        }
        if (lUserID.longValue() &gt; -1) {//先注銷,在登錄
            hCNetSDK.NET_DVR_Logout_V30(lUserID);
            lUserID = new NativeLong(-1);
        }
        System.out.println("注冊里面:lUserId:"+lUserID);
        //注冊(既登錄設備)開始
        m_sDeviceIP = ip;
        m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V30();//獲取設備參數結構
        System.out.println("注冊里面:ip:"+m_sDeviceIP+"     info:"+m_strDeviceInfo);
        lUserID = hCNetSDK.NET_DVR_Login_V30(m_sDeviceIP, (short) Integer.parseInt("8000"), name, password, m_strDeviceInfo);//登錄設備
//        NativeLong lUserID, int dwCommand, NativeLong lChannel, Pointer lpInBuffer, int dwInBufferSize
        System.out.println("登錄后的id"+lUserID);
        int i = hCNetSDK.NET_DVR_GetLastError();

        System.out.println("登錄錯誤代碼:"+i);
        m_strIpparaCfg = new HCNetSDK.NET_DVR_IPPARACFG();
        Pointer lpIpParaConfig = m_strIpparaCfg.getPointer();
        boolean b = hCNetSDK.NET_DVR_SetDVRConfig(lUserID, HCNetSDK.NET_DVR_GET_IPPARACFG, new NativeLong(0), lpIpParaConfig, m_strIpparaCfg.size());
        int seti = hCNetSDK.NET_DVR_GetLastError();
        System.out.println("setConfig"+seti);
        System.out.println("b:"+b);
        long userID = lUserID.longValue();
        System.out.println("注冊里面:userId:"+userID);
        if (userID == -1) {
            m_sDeviceIP = "";//登錄未成功,IP置為空
            return 3;//"注冊失敗";
        }

        return 0;
    }

    /**
     * 獲取設備通道
     */
    public int getChannelNumber() {
        IntByReference ibrBytesReturned = new IntByReference(0);//獲取IP接入配置參數
        boolean bRet = false;
        int iChannelNum = -1;

        m_strIpparaCfg = new HCNetSDK.NET_DVR_IPPARACFG();
        m_strIpparaCfg.write();
        Pointer lpIpParaConfig = m_strIpparaCfg.getPointer();

        bRet = hCNetSDK.NET_DVR_GetDVRConfig(lUserID, HCNetSDK.NET_DVR_GET_IPPARACFG, new NativeLong(0), lpIpParaConfig, m_strIpparaCfg.size(), ibrBytesReturned);
        int geti = hCNetSDK.NET_DVR_GetLastError();
        System.out.println("geti:"+geti);
        m_strIpparaCfg.read();

        String devices = "";
        System.out.println("bRet:"+bRet);
        if (!bRet) {
            //設備不支持,則表示沒有IP通道
            System.out.println("C:"+m_strDeviceInfo.byChanNum);
            for (int iChannum = 0; iChannum &lt; m_strDeviceInfo.byChanNum; iChannum++) {
                devices = "Camera" + (iChannum + m_strDeviceInfo.byStartChan);
            }
        } else {
            System.out.println("IP"+HCNetSDK.MAX_IP_CHANNEL);
            for (int iChannum = 0; iChannum &lt; HCNetSDK.MAX_IP_CHANNEL; iChannum++) {
                if (m_strIpparaCfg.struIPChanInfo[iChannum].byEnable == 1) {
                    devices = "IPCamera" + (iChannum + m_strDeviceInfo.byStartChan);
                }
            }
        }
        System.out.println("通道:"+devices);
        if (devices != null &amp;&amp; devices != "") {
            if (devices.charAt(0) == 'C') {//Camara開頭表示模擬通道
                //子字符串中獲取通道號
                System.out.println("C");
                iChannelNum = Integer.parseInt(devices.substring(6));
            } else {
                if (devices.charAt(0) == 'I') {//IPCamara開頭表示IP通道
                    System.out.println("I");
                    //子字符創中獲取通道號,IP通道號要加32
                    iChannelNum = Integer.parseInt(devices.substring(8)) + 32;
                } else {
                    return 4;
                }
            }
        }
        return iChannelNum;
    }

    /**
     * 獲取通道信號狀態
     *
     * @param channum
     * @return
     */
    public int getSignalStatus(int channum) {
        //獲取設備狀態
        HCNetSDK.NET_DVR_WORKSTATE_V30 devwork = new HCNetSDK.NET_DVR_WORKSTATE_V30();
        if (!hCNetSDK.NET_DVR_GetDVRWorkState_V30(lUserID, devwork)) {
            //返回Boolean值,判斷是否獲取設備能力
            System.out.println("返回設備狀態失敗");
        }
        return devwork.struChanStatic[channum].bySignalStatic;
    }

    /**
     * 拍照
     *
     * @return
     */
    public boolean takePic() {
        //拍照
        HCNetSDK.NET_DVR_JPEGPARA strJpeg = new HCNetSDK.NET_DVR_JPEGPARA();
        strJpeg.wPicQuality = 1; //圖像參數
        strJpeg.wPicSize = 2;
        String filePath = "E:\\123q.jpg";
        lPreviewHandle.setValue(m_strDeviceInfo.byStartChan + 32);
        boolean b = hCNetSDK.NET_DVR_CaptureJPEGPicture(lUserID, lPreviewHandle, strJpeg, filePath);//嘗試用NET_DVR_CaptureJPEGPicture_NEW方法,但不是報43就是JDK崩潰....
        if (!b) {//單幀數據捕獲圖片
            System.out.println("抓拍失敗!" + " err: " + hCNetSDK.NET_DVR_GetLastError());
        } else {
            System.out.println("抓拍成功");
        }
        return b;
    }

    /**
     * 釋放SDK
     */
    public void shutDownDev() {
        //如果已經注冊,注銷
        if (lUserID.longValue() &gt; -1) {
            hCNetSDK.NET_DVR_Logout_V30(lUserID);
        }
        hCNetSDK.NET_DVR_Cleanup();
    }

}

分別調用就行了

Linux下運行成功的截圖
在這里插入圖片描述

win准備和集成

上面linux都集成好了,windows就只是需要修改一點東西就好了

因為我下載的是最新的linux SDK所以HCNetSDK.java就不需要做更改

  1. 繼續新建文件夾 引入win下面的dll文件 全部引入

    在這里插入圖片描述

  2. 因為上面的初始化類判斷了linux和windows系統的,所以直接調用就可以了,因為linux下的sdk中的方法和win的方法基本一致,所以直接用就行了
    在這里插入圖片描述

總結

集成linux出現的問題就是加載不到庫,在摸索官方的sdk后,終於成功,還是自己太年輕,sdk看得不夠多


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM