海康解碼器對接總結(java 版)

本文只是對接海康解碼器的動態解碼功能,即配置解碼器大屏上指定的某個窗口去解某一路IP視頻源。前端

1. 首先,定義所需的結構體與接口。海康SDK中包含的結構體與接口很是之多,在官方的例子中,實現了大部分的結構體與接口,致使一個類的代碼行數高達4000多行。可是咱們沒必要每個都實現,咱們只須要實現須要用到的結構體與接口便可,以下:
package darwin.soc;
import com.sun.jna.*;
import com.sun.jna.ptr.IntByReference;
import java.util.Arrays;
import java.util.List;

//SDK接口說明,HCNetSDK.dll
public interface HCNetSDK extends Library {

    HCNetSDK INSTANCE = (HCNetSDK) Native.loadLibrary("hcnetsdk",
            HCNetSDK.class);
    /*** 宏定義***/
    public static final int SERIALNO_LEN = 48;
    public static final int MAX_DOMAIN_NAME = 64;
    public static final int STREAM_ID_LEN = 32;
    public static final int NAME_LEN = 32;
    public static final int PASSWD_LEN = 16;
    public static final int URL_LEN = 240;



    /*** 結構體定義***/
    public static class NET_DVR_DEVICEINFO_V30 extends Structure{
        public  byte[] sSerialNumber = new byte[SERIALNO_LEN];
        public  byte byAlarmInPortNum;
        public  byte byAlarmOutPortNum;
        public  byte byDiskNum;
        public  byte byDVRType;
        public  byte byChanNum;
        public  byte byStartChan;
        public  byte byAudioChanNum;
        public  byte byIPChanNum;
        public  byte[] byRes1 = new byte[24];

        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList("sSerialNumber","byAlarmInPortNum","byAlarmOutPortNum",
                    "byDiskNum","byDVRType","byChanNum","byStartChan","byAudioChanNum",
                    "byIPChanNum","byRes1");
        }
    }

    public static class NET_DVR_PU_STREAM_CFG_V41 extends Structure{
        public int dwSize;
        public byte byStreamMode;
        public byte[] byRes1 = new byte[3];
        public NET_DVR_DEC_STREAM_MODE uDecStreamMode;
        public byte[] byRes2 = new byte[64];

        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList("dwSize","byStreamMode","byRes1","uDecStreamMode","byRes2");
        }
    }

    public static class NET_DVR_DEC_STREAM_MODE extends Union{

        public NET_DVR_DEC_STREAM_DEV_EX struDecStreamDev;
        public NET_DVR_PU_STREAM_URL struUrlInfo;
        public NET_DVR_DEC_DDNS_DEV struDdnsDecInfo;
        public byte[] byRes = new byte[300];

        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList("struDecStreamDev","struUrlInfo","struDdnsDecInfo","byRes");
        }
    }


    public static class NET_DVR_DEC_STREAM_DEV_EX extends Structure{
        public NET_DVR_STREAM_MEDIA_SERVER struStreamMediaSvrCfg;
        public NET_DVR_DEV_CHAN_INFO_EX struDevChanInfo;

        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList("struStreamMediaSvrCfg","struDevChanInfo");
        }
    }

    public static class NET_DVR_PU_STREAM_URL extends Structure{
        public byte byEnable;
        public byte[] strURL = new byte[URL_LEN];
        public byte byTransPortocol;
        public short wIPID;
        public byte byChannel;
        public byte[] byRes = new byte[7];

        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList("byEnable","strURL","byTransPortocol","wIPID","byChannel","byRes");
        }
    }

    public static class NET_DVR_DEC_DDNS_DEV extends Structure{
        public NET_DVR_DEV_DDNS_INFO struDdnsInfo;
        public NET_DVR_STREAM_MEDIA_SERVER struMediaServer;

        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList("struDdnsInfo","struMediaServer");
        }
    }

    public static class NET_DVR_STREAM_MEDIA_SERVER extends Structure{
        public byte byValid;
        public byte[] byRes1 = new byte[3];
        public byte[] byAddress = new byte[MAX_DOMAIN_NAME];
        public short wDevPort;
        public byte byTransmitType;
        public byte[] byRes2 = new byte[5];

        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList("byValid","byRes1","byAddress","wDevPort","byTransmitType","byRes2");
        }
    }

    public static class NET_DVR_DEV_CHAN_INFO_EX extends Structure{
        public byte byChanType;
        public byte[] byStreamId = new byte[STREAM_ID_LEN];
        public byte[] byRes1 = new byte[3];
        public int dwChannel;
        public byte[] byRes2 = new byte[24];
        public byte[] byAddress = new byte[MAX_DOMAIN_NAME];
        public short wDVRPort;
        public byte byChannel;
        public byte byTransProtocol;
        public byte byTransMode;
        public byte byFactoryType;
        public byte byDeviceType;
        public byte byDispChan;
        public byte bySubDispChan;
        public byte byResolution;
        public byte[] byRes = new byte[2];
        public byte[] sUserName = new byte[NAME_LEN];
        public byte[] sPassword = new byte[PASSWD_LEN];

        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList("byChanType","byStreamId","byRes1","dwChannel","byRes2","byAddress","wDVRPort",
                    "byChannel","byTransProtocol","byTransMode","byFactoryType","byDeviceType","byDispChan",
                    "bySubDispChan","byResolution","byRes","sUserName","sPassword");
        }
    }

    public static class NET_DVR_DEV_DDNS_INFO extends Structure{
        public byte[] byDevAddress = new byte[MAX_DOMAIN_NAME];
        public byte byTransProtocol;
        public byte byTransMode;
        public byte byDdnsType;
        public byte byRes1;
        public byte[] byDdnsAddress = new byte[MAX_DOMAIN_NAME];
        public short wDdnsPort;
        public byte byChanType;
        public byte byFactoryType;
        public short dwChannel;
        public byte[] byStreamId = new byte[STREAM_ID_LEN];
        public byte[] sUserName = new byte[NAME_LEN];
        public byte[] sPassword = new byte[PASSWD_LEN];
        public short wDevPort;
        public byte[] byRes2 = new byte[2];

        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList("byDevAddress","byTransProtocol","byTransMode","byDdnsType","byRes1","byDdnsAddress",
                    "wDdnsPort","byChanType","byFactoryType","dwChannel","byStreamId","sUserName","sPassword",
                    "wDevPort","byRes2");
        }
    }




    /***  接口定義 ***/

    /**
     * 登陸設備
     * */
    NativeLong  NET_DVR_Login_V30(String sDVRIP, short wDVRPort, String sUserName, String sPassword, NET_DVR_DEVICEINFO_V30 lpDeviceInfo);
    /**
     * 退出登陸
     * */
    boolean  NET_DVR_Logout(NativeLong lUserID);
    /**
     * 初始化SDK
     * */
    boolean  NET_DVR_Init();
    /**
     * 清理資源
     * */
    boolean  NET_DVR_Cleanup();
    /**
     * 獲取錯誤碼
     * */
    int  NET_DVR_GetLastError();

    /**
     * 重啓設備
     * */
    boolean  NET_DVR_RebootDVR(NativeLong lUserID);

    /**
     * 動態解碼
     * */
    boolean NET_DVR_MatrixStartDynamic_V41(NativeLong lUserID,int dwDecChanNum,Pointer lpDynamicInfo);

    /**
     * 獲取窗口解碼開關
     * */
    boolean  NET_DVR_MatrixGetDecChanEnable(NativeLong lUserID, int dwDecChanNum, IntByReference lpdwEnable);
}

2.開始編寫入口類,調用NET_DVR_MatrixStartDynamic_V41方法,以下:java

package darwin.soc;

import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;

/**
 * @copyright: Copyright (c) 2015-2025
 * @company:
 * @author: hjw
 * @date: 2018-02-02 17:21
 * @description: 加載海康SDK的工具類
 */
public class LoadSDKUtil {

    private static HCNetSDK hcNetSDK = HCNetSDK.INSTANCE;

    //SDK初始化成功的標誌
    private static boolean initSDKSuccess = false;

    static {
        initSDKSuccess = hcNetSDK.NET_DVR_Init();
    }

    /**
     * @Author: hjw
     * @Date:  2018-02-05 14:16
     * @Param:
     * @Return:
     * @Description: 登陸設備
     */
    public static long loginDevice(String ip,int port,String userName,String password){
        if(!initSDKSuccess){
            return -1;
        }
        HCNetSDK.NET_DVR_DEVICEINFO_V30 deviceinfo_v30 = new HCNetSDK.NET_DVR_DEVICEINFO_V30();
        NativeLong lUserID = hcNetSDK.NET_DVR_Login_V30(ip,(short) port,userName,password,deviceinfo_v30);
        return lUserID.longValue();
    }

    //拿到信號源信息結構體的指針
    public static Pointer getIPCInfoPointer(String ipAddress,short port,String userName,String passWord){
        //動態解碼
        HCNetSDK.NET_DVR_PU_STREAM_CFG_V41 m_struDynamicInfo = new HCNetSDK.NET_DVR_PU_STREAM_CFG_V41();
        m_struDynamicInfo.dwSize = m_struDynamicInfo.size();
        //直接從設備取流
        m_struDynamicInfo.byStreamMode=(byte)1;
        //聯合體須要設置Type
        m_struDynamicInfo.uDecStreamMode.setType(HCNetSDK.NET_DVR_DEC_STREAM_DEV_EX.class);
        m_struDynamicInfo.uDecStreamMode.read();

        //前端設 備 IP 地址
        for(int i = 0; i < HCNetSDK.MAX_DOMAIN_NAME; i++){
            m_struDynamicInfo.uDecStreamMode.struDecStreamDev.struDevChanInfo.byAddress[i] = 0;
        }
        for(int i = 0; i < ipAddress.length(); i++){
            m_struDynamicInfo.uDecStreamMode.struDecStreamDev.struDevChanInfo.byAddress[i] = ipAddress.getBytes()[i];
        }
        //前端設備服務端口
        m_struDynamicInfo.uDecStreamMode.struDecStreamDev.struDevChanInfo.wDVRPort = port;

        //前端設備登 錄用戶名
        for(int i = 0; i < HCNetSDK.NAME_LEN; i++){
            m_struDynamicInfo.uDecStreamMode.struDecStreamDev.struDevChanInfo.sUserName[i] = 0;
        }
        for(int i = 0; i < userName.length(); i++){
            m_struDynamicInfo.uDecStreamMode.struDecStreamDev.struDevChanInfo.sUserName[i] = userName.getBytes()[i];
        }
        //前端設備登 錄密碼
        for(int i = 0; i < HCNetSDK.PASSWD_LEN; i++){
            m_struDynamicInfo.uDecStreamMode.struDecStreamDev.struDevChanInfo.sPassword[i] = 0;
        }
        for(int i = 0; i < passWord.length(); i++){
            m_struDynamicInfo.uDecStreamMode.struDecStreamDev.struDevChanInfo.sPassword[i] = passWord.getBytes()[i];
        }

        //取通道 1 的碼流
        m_struDynamicInfo.uDecStreamMode.struDecStreamDev.struDevChanInfo.byChannel =(byte) 1;
        //廠家私有協議
        m_struDynamicInfo.uDecStreamMode.struDecStreamDev.struDevChanInfo.byFactoryType =(byte) 0;
        m_struDynamicInfo.write();
        Pointer pointer = m_struDynamicInfo.getPointer();
        return pointer;
    }

    //動態解碼
    public static void startDynamicDecode(NativeLong lUserID,int winNo,String ipAddress,short port,String userName,
                                          String passWord){
        //視頻源信息結構體指針
        Pointer pointer = getIPCInfoPointer(ipAddress,port,userName,passWord);
        //窗口號,表明第一組大屏第winNo個窗口
        int dwChannelEx = 1<<24|1<<16|winNo;
        boolean flag = hcNetSDK.NET_DVR_MatrixStartDynamic_V41(lUserID,dwChannelEx, pointer);
        if(!flag){
            int errorCode = hcNetSDK.NET_DVR_GetLastError();
            System.out.println("動態解碼出錯:" + errorCode);
        }
    }
    public static void main(String[] args) throws InterruptedException {
        //登陸解碼器(解碼器的用戶名與密碼)
        long userId = loginDevice("192.168.10.77",8000,"admin","hu328704547");
        System.out.println("userId:" + userId);
        NativeLong lUserID = new NativeLong(userId);
        if(userId ==  -1){
            int errorCode = hcNetSDK.NET_DVR_GetLastError();
            System.out.println("Error Code:" + errorCode);
        }
        //解碼
        try {
            String ip = "192.168.10.66";
            short port = 8000;
            String userName = "admin";
            String passWord = "1qaz2wsx";

           /* String ip = "192.168.10.65";
            short port = 8000;
            String userName = "admin";
            String passWord = "admin1234567890";*/
            startDynamicDecode(lUserID,1,ip,port,userName,passWord);
        }catch (Exception e){
            e.printStackTrace();
        }
        hcNetSDK.NET_DVR_Logout(lUserID);
        hcNetSDK.NET_DVR_Cleanup();
        System.out.println("ended!!!");
    }
}

須要注意的是:數組

1.NET_DVR_PU_STREAM_CFG_V41結構體中的uDecStreamMode屬性不是一個結構體,而是一個Union,因此uDecStreamMode屬性具體使用其下面哪個屬性,須要使用m_struDynamicInfo.uDecStreamMode.setType(HCNetSDK.NET_DVR_DEC_STREAM_DEV_EX.class); 來進行指定。ide

2.當結構體中的某個屬性是字節數組時,不該該使用getBytes()方法直接賦值(由於這樣會致使字節數組的長度發生變化),而是如我上面的代碼片斷那樣循環來爲字節數組中的每個字節賦值。工具

相關文章
相關標籤/搜索