海康SDK編程指南(C#二次開發版本)

轉載於整理自:心澄欲遣

目前使用的海康SDK包括IPC_SDK(硬件設備),Plat_SDK(平臺),其中兩套SDK都需單獨調用海康播放庫PlayCtrl.dll來解碼視頻流,返回視頻信息和角度信息。本文僅對視頻監控常用功能的使用進行說明,其它未實現功能請參看設備網絡SDK使用手冊播放庫編程指南V7.2

IPC_SDK編程指南

(一)    SDK的引用

由於IPC_SDK沒有SDK安裝程序,所以需手工把下面圖表中的DLL放入Debug或者Release文件夾的根目錄下供程序調用,或者加入系統環境變量Path下。

 

名稱

版本號

說明

AudioIntercom.dll

1.1.0.5

 

AudioRender.dll

1.0.0.2

 

DsSdk.dll

6.0.10.922

 

gdiplus.dll

 

微軟庫

HCNetSDK.dll

4.3.0.6

網絡功能調用,大量功能調用此庫

OpenAL32.dll

 

 

PlayCtrl.dll

7.2.0.0

播放庫,定製版本,增加返角回調及數據結構

QosControl.dll

1.0.0.1

 

StreamTransClient.dll

1.1.2.12

 

SuperRender.dll

1.0.1.0

 

SystemTransform.dll

2.4.0.3

設備信息轉發,根據播放庫修改過

(二)    C#程序調用DLL中的非託管函數方法

1.        調用外部聲明方法

首先在C#語言源程序中聲明外部方法,其基本形式是:

[DLLImport(“DLL文件”)]

修飾符 extern 返回變量類型 方法名稱 (參數列表)

例如:

using System.Runtime.InteropServices;
 
[DllImport("HCNetSDK.dll")]
public static extern bool NET_DVR_Init();

注意:

1)        需要在程序聲明中使用System.Runtime.InteropServices命名空間。     DllImport只能放置在方法聲明上。

2)        DLL文件必須位於程序當前目錄或系統定義的查詢路徑中(即:系統環境變量中Path所設置的路徑)。

3)        返回變量類型、方法名稱、參數列表一定要與DLL文件中的定義相一致。

4)        若要使用其它函數名,可以使用EntryPoint屬性設置,如:[DllImport("user32.dll", EntryPoint="MessageBoxA")]

static extern int MsgBox(int hWnd, string msg, string caption, int type);

5)        其它可選的 DllImportAttribute 屬性:

CharSet 指示用在入口點中的字符集,如:CharSet=CharSet.Ansi;

SetLastError 指示方法是否保留 Win32"上一錯誤",如:SetLastError=true;

ExactSpelling 指示 EntryPoint 是否必須與指示的入口點的拼寫完全匹配,

如:ExactSpelling=false;

PreserveSig指示方法的簽名應當被保留還是被轉換, 如:PreserveSig=true;

CallingConvention指示入口點的調用約定, 如:CallingConvention=CallingConvention.Winapi;

2.        參數數據類型轉換(詳細參考這裏

Win32 Types

CLR Type

char,INT8,SBYTE,CHAR

System.SByte

short,short int,INT16,SHORT

System.Int16

int,long,long int,INT32,LONG32,BOOL,INT

System.Int32

_int64,INT64,LONGLONG

System.Int64

unsigned char,UINT8,UCHAR,BYTE

System.Byte

unsigned short,UINT16,USHORT,WORD,ATOM,WCHAR,__wchar_t

System.UInt16

unsigned,unsigned int,UINT32,ULONG32,DWORD32,ULONG,DWORD,UINT

System.UInt32

unsigned __int64,UINT64,DWORDLONG,ULONGLONG

System.UInt64

float,FLOAT

System.Single

double,long double,DOUBLE

System.Double

BSTR

StringBuilder

LPCTSTR

StringBuilder

LPCWSTR

IntPtr

handle

IntPtr

hwnd

IntPtr

char * 

string

int *

ref int

int &

ref int

void *

IntPtrs

unsigned char * 

ref byte

BOOL ——

bool

DWORD

uint或int

注意:

  1. 指針做參數時在C#中一定要使用ref 或out關鍵字,尤其是結構體指針,要不會報內存讀取錯誤
  2. 首先聲明結構體 [StructLayoutAttribute(LayoutKind.Sequential)]
  3. 重寫結構體的時候,之前有指明類型長度或數組長度的地方,也要進行相應的標註,要不也會導致內存錯誤

3.        重寫結構體

例如:[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)],具體長度需參看SDK中改結構體的說明文檔

或者  [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 64, ArraySubType = UnmanagedType.I1)]

4.        結構體與指針之間的轉換

1)        結構體轉換爲指針

Hik.NET_DVR_IPPARACFG_V40 ipParaCfgV40 = new Hik.NET_DVR_IPPARACFG_V40();//初始化結構體
Int32 size = Marshal.SizeOf(ipParaCfgV40);//返回結構體字節數
IntPtr ptrIpParaCfgV40 = Marshal.AllocHGlobal(size);//定義指針字節數
Marshal.StructureToPtr(ipParaCfgV40, ptrIpParaCfgV40, false);//將結構體封裝到內存指針中
//調用需要指針的方法
Marshal.FreeHGlobal(ptrIpParaCfgV40);//釋放指針

2)        指針轉換爲結構體

Hik.NET_DVR_CAMERAPARAMCFG_EX cameraParamCfg = new Hik.NET_DVR_CAMERAPARAMCFG_EX();//實例化結構體
Int32 size = Marshal.SizeOf(cameraParamCfg );//獲取結構體字節數
IntPtr ptrCfg = Marshal.AllocHGlobal(size);//爲指針分配空間
//調用獲取指針的方法
cameraParamCfg = (Hik.NET_DVR_CAMERAPARAMCFG_EX)Marshal.PtrToStructure(ptrCfg, typeof(Hik.NET_DVR_CAMERAPARAMCFG_EX));//把指針轉換爲結構體
Marshal.FreeHGlobal(ptrCfg);//釋放指針

3)        指針轉換爲結構體精簡寫法

Int32 size = Marshal.SizeOf(typeof(Hik.NET_DVR_PTZPOS));
IntPtr ptrPTZ = Marshal.AllocHGlobal(size);
//調用獲取指針的方法
Hik.NET_DVR_PTZPOS PTZPos = (Hik.NET_DVR_PTZPOS)Marshal.PtrToStructure(ptrPTZ, typeof(Hik.NET_DVR_PTZPOS));//指針轉換爲結構體
Marshal.FreeHGlobal(ptrPTZ);//釋放指針

對第2點和第3點的說明:當一個方法的參數爲一個結構體的指針時,並且執行方法後此指針會返回結構體信息時,可以有兩種方式來初始化這個指針,第二種更爲簡潔些。

(三)    SDK的調用

對IPC_SDK的C#封裝類見附件Hik.cs(類似我們CHCNetSDK.cs),可參考此基礎類文件進行程序功能編寫。

(類似我們的HKIPCamera.cs類來調用CHCNetSDK類的win32函數)

1.        獲取錯誤碼

Hik.NET_DVR_GetLastError();//獲取錯誤碼

使用方式:如果有個非託管函數方法返回結果爲false,則調用此方法獲取錯誤碼。

例如:

ret = Hik.NET_DVR_Init();
if (ret != true)
    throw new HikException(Hik.NET_DVR_GetLastError());//HikException爲自定義異常調用類,用來解析錯誤碼拋出異常

2.        登錄

1)        用戶註冊

Hik.NET_DVR_Init();//初始化SDK,多次初始化會拋出錯誤
Hik.NET_DVR_SetConnectTime(2000, 1);//設置超時時間
Hik.NET_DVR_SetReconnect(10000, 1);//設置重連時間
Hik.NET_DVR_DEVICEINFO_V30 _deviceInfo = new Hik.NET_DVR_DEVICEINFO_V30();//設備參數結構體,可以返回設備信息
String userId = Hik.NET_DVR_Login_V30(IP,Port,UserName,Password,ref _deviceInfo);//登錄後,獲取用戶ID和設備信息供後續方法調用

2)        用戶註銷

Hik.NET_DVR_StopRealPlay(_realHandle);//如果有預覽視頻,則根據其播放句柄關閉視頻
Hik.NET_DVR_Logout(_userId);//根據用戶ID註銷用戶登錄
Hik.NET_DVR_Cleanup();//必須執行的釋放IPC_SDK

3.        獲取通道號

由於IPC_SDK同時支持IPC與NVR,所以兩者獲取通道號的方式有所不同。

1)        獲取IPC設備通道號

如果Hik.NET_DVR_DEVICEINFO_V30結構體中byChanNum模擬通道數量屬性值大於0,則代表登錄設備爲IPC設備,需要獲取其模擬通道號byStartChan屬性的值。每組模擬通道號範圍爲0-32。

for (Int32 i = 0; i < _deviceInfo.byChanNum; i++) //一個IPC設備可以設置多個模擬通道號,默認爲一個模擬通道號
{
    Int channelId = _deviceInfo.byStartChan
}

2)        獲取NVR設備通道號

如果Hik.NET_DVR_DEVICEINFO_V30結構體中byIPChanNum數字通道數量屬性值大於0,則代表登錄設備爲NVR設備,需要獲取其數字通道號,其獲取方法要比獲取IPC設備通道號複雜。每組數字通道號範圍爲33-64。

public void InfoIPChannel()
        {
 
            Hik.NET_DVR_IPPARACFG_V40 ipParaCfgV40 = new Hik.NET_DVR_IPPARACFG_V40();
            Int32 size = Marshal.SizeOf(ipParaCfgV40);
 
            IntPtr ptrIpParaCfgV40 = Marshal.AllocHGlobal(size);
            Marshal.StructureToPtr(ipParaCfgV40, ptrIpParaCfgV40, false);
 
            UInt32 result = 0;
            Int32 groupNo = 0;
            Boolean ret = Hik.NET_DVR_GetDVRConfig(_userId, Hik.NET_DVR_GET_IPPARACFG_V40, groupNo, ptrIpParaCfgV40, (UInt32)size, ref result);//獲取配置信息
            if (ret)
            {
                ipParaCfgV40 = (Hik.NET_DVR_IPPARACFG_V40)Marshal.PtrToStructure(ptrIpParaCfgV40, typeof(Hik.NET_DVR_IPPARACFG_V40));
 
                byte byStreamType;
                for (Int32 i = 0; i < ipParaCfgV40.dwDChanNum; i++)
                {
 
                    byStreamType = ipParaCfgV40.struStreamMode[i].byGetStreamType;
                    size = Marshal.SizeOf(ipParaCfgV40.struStreamMode[i].uGetStream);
 
                    switch (byStreamType)
                    {
                        //目前NVR僅支持直接從設備取流 NVR supports only the mode: get stream from device directly
                        case 0:
                            IntPtr ptrChanInfo = Marshal.AllocHGlobal(size);
                            Marshal.StructureToPtr(ipParaCfgV40.struStreamMode[i].uGetStream, ptrChanInfo, false);
                            Hik.NET_DVR_IPCHANINFO _struChanInfo = (Hik.NET_DVR_IPCHANINFO)Marshal.PtrToStructure(ptrChanInfo, typeof(Hik.NET_DVR_IPCHANINFO));
                            Int32 deviceId = _struChanInfo.byIPID + _struChanInfo.byIPIDHigh * 256 - groupNo * 64 - 1;
                            if (deviceId == -1)
                                continue;
                            _channelInfoList.Add(new ChannelInfo() { DeviceID = deviceId, ChannelID = i + (Int32)ipParaCfgV40.dwStartDChan, State = (Int32)_struChanInfo.byEnable, IP = ipParaCfgV40.struIPDevInfo[i].struIP.sIpV4 });//獲取數字通道信息封裝到自定義通道類中
                            Marshal.FreeHGlobal(ptrChanInfo);
                            break;
                        default:
                            break;
                    }
                }
            }
            Marshal.FreeHGlobal(ptrIpParaCfgV40);
        }

4.        預覽

1)        初始化預覽結構體

Hik.NET_DVR_PREVIEWINFO previewInfo = new Hik.NET_DVR_PREVIEWINFO();
previewInfo.lChannel = channelId;//預覽的設備通道 the device channel number
previewInfo.dwStreamType = 0;//碼流類型:0-主碼流,1-子碼流,2-碼流3,3-碼流4,以此類推
previewInfo.dwLinkMode = 0;//連接方式:0- TCP方式,1- UDP方式,2- 多播方式,3- RTP方式,4-RTP/RTSP,5-RSTP/HTTP 
previewInfo.hPlayWnd = IntPtr.Zero;//預覽窗口,如果不使用回調顯示視頻流,則此處可以設置顯示窗口句柄
previewInfo.bBlocked = true; //0- 非阻塞取流,1- 阻塞取流

2)        獲取實時視頻流和視頻句柄

_realHandle = Hik.NET_DVR_RealPlay_V40(UserId, ref previewInfo, realData, IntPtr.Zero);//返回實時流句柄供後續方法調用

參數說明:

UserID爲登錄後返回的用戶句柄,

previewInfo爲已實例化的預覽結構體

realData爲預覽實時流回調函數,如果直接在窗口顯示實時流而不通過回調方式,則此參數可以設置爲null

3)        實時流回調函數的使用

在封裝類(CHCNetSDK)中定義回調函數:

/// <summary>
/// 預覽實時流回調函數
/// </summary>
/// <param name="lRealHandle">當前的預覽句柄</param>
/// <param name="dwDataType">數據類型:1系統頭數據,2流數據(包括複合流或音視頻分開的視頻流數據),3音頻數據</param>
/// <param name="pBuffer">存放數據的緩衝區指針</param>
/// <param name="dwBufSize">緩衝區大小</param>
/// <param name="pUser">用戶數據</param>
public delegate void REALDATACALLBACK(Int32 lRealHandle, UInt32 dwDataType, IntPtr pBuffer, UInt32 dwBufSize, IntPtr pUser);

使用時注意:實例化實時流回調函數時,不能在方法內聲明並實例化,否則會被回收機制提前釋放實例化對象,導致程序錯誤。需要在最外部調用類中作爲字段預先聲明。

例如:(HKIPCamera類中)

private Hik.REALDATACALLBACK _callback;//實時流回調,作爲字段聲明
public override int IncreaseClient()
{
    if (_callback == null)
         _callback = new Hik.REALDATACALLBACK(RealDataCallBack);//RealDataCallBack是一個方法
         Hik.StartPlay(Hik.ChannelInfoList[0].ChannelID, _callback);//播放實時流視頻
}

簡易流程描述爲:實時流回調函數返回實時視頻流,然後把實時視頻流傳入到播放庫解碼(PlayCtrl.dll),通過播放庫的兩個回調函數來返回解析後的視頻流和角度。角度回調信息的格式爲我公司定製協議,具體內容參看角度信息私有數據格式,59個字節長度的16進制字符串。

private Hik.DECCBFUN _displayCallback;//解碼回調
private Hik.ADDITIONDATACBFUN _additionDataDisplayCallback;//角度回調

獲取播放庫錯誤碼

Int port;
PlayM4_GetPort(ref port);//首先需獲取播放句柄
PlayM4_GetLastError(port);//獲取播放庫錯誤碼

具體回調如下:

int port;播放庫端口號 
switch (dwDataType)
{
        case 1:     // sys head 系統頭數據
        if (dwBufSize > 0)
        {
           //獲取播放句柄 Get the port to play
           PlayM4_GetPort(ref _port);
           //設置流播放模式
           PlayM4_SetStreamOpenMode(_port, 0);
           //打開碼流,送入頭數據 Open stream
          PlayM4_OpenStream(_port, pBuffer, dwBufSize, 2 * 1024 * 1024);
           //設置顯示緩衝區個數 
           PlayM4_SetDisplayBuf(_port, 15);
           //設置解碼回調函數,獲取解碼後音視頻原始數據 Set callback function of decoded data
           PlayM4_SetDecCallBackEx(_port, displayFun, IntPtr.Zero, 0);
           //設置角度回調函數,獲取解碼前角度信息
          PlayM4_SetAdditionDataCallBack(_port, 0x1004, additionDataDisplayFun, IntPtr.Zero);
          //開始解碼 Start to play  
          PlayM4_Play(_port, IntPtr.Zero);//最後一個參數表示播放窗體的指針
          }
          break;
          case 2:     // video stream data 視頻流數據(包括複合流和音視頻分開的視頻流數據)
          if (dwBufSize > 0 && _port != -1)
          {
            for (Int32 i = 0; i < 999; i++)
            {
              //送入碼流數據進行解碼 Input the stream data to decode
             if (!PlayM4_InputData(_port, pBuffer, dwBufSize))
                Thread.Sleep(2);
            else
                 break;  
                      }
            }
           break;
          default:
           if (dwBufSize > 0 && _port != -1)
           {
              //送入其他數據 Input the other data
             for (Int32 i = 0; i < 999; i++)
             {
              if (!PlayM4_InputData(_port, pBuffer, dwBufSize))
                  Thread.Sleep(2);
              else
                  break;
              }
            }
              break;
            }

4)        停止預覽

Hik.NET_DVR_StopRealPlay(_realHandle);//_realHandle爲播放句柄

5.        雲臺控制

1)        雲臺操作命令

            SET_PRESET = 8,// 設置預置點 
            CLE_PRESET = 9,// 清除預置點 
            Up = 21,/* 雲臺以SS的速度上仰 */
            Down = 22,/* 雲臺以SS的速度下俯 */
            Left = 23,/* 雲臺以SS的速度左轉 */
            Right = 24,/* 雲臺以SS的速度右轉 */
            UpLeft = 25,/* 雲臺以SS的速度上仰和左轉 */
            UpRight = 26,/* 雲臺以SS的速度上仰和右轉 */
            DownLeft = 27,/* 雲臺以SS的速度下俯和左轉 */
            DownRight = 28,/* 雲臺以SS的速度下俯和右轉 */
            Auto = 29,/* 雲臺以SS的速度左右自動掃描 */
            ZOOM_IN = 11,/* 焦距以速度SS變大(倍率變大) */
            ZOOM_OUT = 12,/* 焦距以速度SS變小(倍率變小) */
            FOCUS_NEAR = 13,  /* 焦點以速度SS前調 */
            FOCUS_FAR = 14,  /* 焦點以速度SS後調 */
            IRIS_OPEN = 15,  /* 光圈以速度SS擴大 */
            IRIS_CLOSE = 16,  /* 光圈以速度SS縮小 */
            GOTO_PRESET = 39/* 快球轉到預置點 */

2)        雲臺操作方法

根據定製協議,雲臺控制速度爲1-160。但是需保證球機的升級包版本爲IPD_R3_STD_5.2.0_141111。

/// <summary>
/// 帶速度的雲臺控制操作(需先啓動圖像預覽)
/// </summary>
/// <param name="lRealHandle">NET_DVR_RealPlay_V40的返回值</param>
/// <param name="dwPTZCommand">雲臺控制命令</param>
/// <param name="dwStop">雲臺停止動作或開始動作:0- 開始;1- 停止</param>
/// <param name="dwSpeed">雲臺控制的速度,用戶按不同解碼器的速度控制值設置。取值範圍[1,160]</param>
/// <returns>TRUE表示成功,FALSE表示失敗</returns>
bool NET_DVR_PTZControlWithSpeed(int lRealHandle, uint dwPTZCommand, uint dwStop, uint dwSpeed);

6.        雲臺預置位

1)        預置位命令

     SET_PRESET = 8,// 設置預置點 
            CLE_PRESET = 9,// 清除預置點 
            GOTO_PRESET = 39// 轉到預置點 

2)        預置位操作

/// <summary>
/// 設置預置位
/// </summary>
/// <param name="lRealHandle">NET_DVR_RealPlay_V40的返回值</param>
/// <param name="dwPTZPresetCmd">預置位控制命令</param>
/// <param name="dwPresetIndex">預置位編號最多支持255個預置點</param>
/// <returns>TRUE表示成功,FALSE表示失敗</returns>
bool NET_DVR_PTZPreset(int lRealHandle, uint dwPTZPresetCmd, uint dwPresetIndex);

3)        反向操作

Hik.NET_DVR_PTZPreset(_realHandle, (uint)8, 33);

 

7.        獲取設備的配置信息

在設定某些配置時,需預先執行此方法來獲取相關配置信息的結構體。

/// <summary>
/// 獲取設備的配置信息
/// </summary>
/// <param name="lUserID">NET_DVR_Login_V30的返回值</param>
/// <param name="dwCommand">設備配置命令</param>
/// <param name="lChannel">通道號或者組號,不同的命令對應不同的取值</param>
/// <param name="lpOutBuffer">接收數據的緩衝指針</param>
/// <param name="dwOutBufferSize">接收數據的緩衝長度(以字節爲單位),不能爲0</param>
/// <param name="lpBytesReturned">實際收到的數據長度指針,不能爲NULL</param>
/// <returns></returns>
bool NET_DVR_GetDVRConfig(int lUserID, uint dwCommand, int lChannel, IntPtr lpOutBuffer, uint dwOutBufferSize, ref uint lpBytesReturned);

具體調用見下面操作示例

8.        設置設備的配置信息

/// <summary>
/// 設置設備的配置信息
/// </summary>
/// <param name="lUserID">NET_DVR_Login_V30的返回值</param>
/// <param name="dwCommand">設備配置命令</param>
/// <param name="lChannel">通道號或者組號,不同的命令對應不同的取值
<param>
/// <param name="lpInBuffer">輸入數據的緩衝指針</param>
/// <param name="dwInBufferSize">輸入數據的緩衝長度(以字節爲單位)</param>
/// <returns></returns>
bool NET_DVR_SetDVRConfig(int lUserID, uint dwCommand, int lChannel, IntPtr lpInBuffer, uint dwInBufferSize);

具體調用見下面操作示例

9.        日夜切換 (前端參數配置結構體中

1)        設備配置命令

3369; //IPC設置CCD參數配置
3368; //IPC獲取CCD參數配置

2)        通道號或者組號

ChannelId//登錄IPC設備時獲取的通道號

3)        獲取配置信息

Hik.NET_DVR_CAMERAPARAMCFG_EX cameraParamCfg = new Hik.NET_DVR_CAMERAPARAMCFG_EX();//實例化前端參數結構體
Int32 nSize = Marshal.SizeOf(cameraParamCfg );//獲取結構體空間大小
IntPtr ptrCfg = Marshal.AllocHGlobal(nSize);//設置指針大小
Hik.NET_DVR_GetDVRConfig(_userId,3368, _channelId, ptrCfg, (UInt32)nSize, ref dwReturn);//獲取配置信息的指針
cameraParamCfg = (Hik.NET_DVR_CAMERAPARAMCFG_EX)Marshal.PtrToStructure(ptrCfg, typeof(Hik.NET_DVR_CAMERAPARAMCFG_EX));//指針轉換爲數據結構
Marshal.FreeHGlobal(ptrCfg);//釋放指針

4)        日夜切換命令

0白天
1夜晚
2自動

5)        日夜切換結構體

NET_DVR_DAYNIGHT struDayNight;/*日夜轉換*/

6)        設置配置信息

Hik.NET_DVR_CAMERAPARAMCFG_EX cameraParamCfg=獲取配置信息();
Int32 size = Marshal.SizeOf(cameraParamCfg);//獲取結構體大小
IntPtr ptrCfg = Marshal.AllocHGlobal(size);//設置指針空間大小
cameraParamCfg.struDayNight.byDayNightFilterType = (byte)日夜切換命令;
Marshal.StructureToPtr(cameraParamCfg, ptrCfg, false);//結構體轉換爲指針
Hik.NET_DVR_SetDVRConfig(_userId, 3369, _channelId, ptrCfg, (uint)size);//設置參數
Marshal.FreeHGlobal(ptrCfg);//釋放指針

10.    透霧切換(前端參數配置結構體中

1)        設備配置命令

3369; //IPC設置CCD參數配置
3368; //IPC獲取CCD參數配置

2)        通道號或者組號

        ChannelId//登錄IPC設備時獲取的通道號

3)        獲取配置信息

Hik.NET_DVR_CAMERAPARAMCFG_EX cameraParamCfg = new Hik.NET_DVR_CAMERAPARAMCFG_EX();//實例化前端參數結構體
Int32 nSize = Marshal.SizeOf(cameraParamCfg );//獲取結構體空間大小
IntPtr ptrCfg = Marshal.AllocHGlobal(nSize);//設置指針大小
Hik.NET_DVR_GetDVRConfig(_userId,3368, _channelId, ptrCfg, (UInt32)nSize, ref dwReturn);//獲取配置信息的指針
cameraParamCfg = (Hik.NET_DVR_CAMERAPARAMCFG_EX)Marshal.PtrToStructure(ptrCfg, typeof(Hik.NET_DVR_CAMERAPARAMCFG_EX));//指針轉換爲數據結構
Marshal.FreeHGlobal(ptrCfg);//釋放指針

4)        透霧切換命令

0關閉
2開啓

5)        透霧切換結構體

NET_DVR_DEFOGCFG struDefogCfg;//透霧參數

6)        設置配置信息

Hik.NET_DVR_CAMERAPARAMCFG_EX cameraParamCfg=獲取配置信息();
Int32 size = Marshal.SizeOf(cameraParamCfg);//獲取結構體大小
IntPtr ptrCfg = Marshal.AllocHGlobal(size);//設置指針空間大小
cameraParamCfg.struDefogCfg.byMode = (byte)透霧切換命令;
cameraParamCfg.struDefogCfg.byLevel = (byte)100;//透霧級別
Marshal.StructureToPtr(cameraParamCfg, ptrCfg, false);//結構體轉換爲指針
Hik.NET_DVR_SetDVRConfig(_userId, 3369, _channelId, ptrCfg, (uint)size);//設置參數
Marshal.FreeHGlobal(ptrCfg);//釋放指針

11.    聚焦模式切換

1)        設備配置命令

        3306; //設置快球聚焦模式參數
        3305; //獲取快球聚焦模式參數

2)        通道號或者組號

        ChannelId//登錄IPC設備時獲取的通道號

3)        獲取配置信息

Hik.NET_DVR_FOCUSMODE_CFG focusModeCfg = new Hik.NET_DVR_FOCUSMODE_CFG();//實例化聚焦模式結構體
Int32 size = Marshal.SizeOf(focusModeCfg);//獲取結構體大小
IntPtr ptrCfg = Marshal.AllocHGlobal(size);//設置指針空間大小
Hik.NET_DVR_GetDVRConfig(_userId, 3305, _channelId, ptrCfg, (UInt32)size, ref dwReturn);//獲取聚焦模式信息的指針
focusModeCfg = (Hik.NET_DVR_FOCUSMODE_CFG)Marshal.PtrToStructure(ptrCfg, typeof(Hik.NET_DVR_FOCUSMODE_CFG));//指針轉換爲聚焦模式結構體
Marshal.FreeHGlobal(ptrCfg);//釋放指針

4)        聚焦模式切換命令

0自動
1手動
2半自動

5)        聚焦模式切換結構體

NET_DVR_FOCUSMODE_CFG

6)        設置配置信息

Hik.NET_DVR_FOCUSMODE_CFG focusModeCfg = 獲取配置信息();
Int32 size = Marshal.SizeOf(focusModeCfg);//獲取結構體大小
IntPtr ptrCfg = Marshal.AllocHGlobal(size);//設置指針空間大小
focusModeCfg.byFocusMode = (byte)聚焦模式命令;
Marshal.StructureToPtr(focusModeCfg, ptrCfg, false);//結構體轉換爲指針
Hik.NET_DVR_SetDVRConfig(_userId, Hik.NET_DVR_SET_FOCUSMODECFG, _channelId, ptrCfg, (uint)size);//設置聚焦模式
Marshal.FreeHGlobal(ptrCfg);//釋放指針

12.    OSD字符設置

1)        設備配置命令

1030;//獲取疊加字符操作命令
1031;//設置疊加字符操作命令

2)        通道號或者組號

ChannelId//登錄IPC設備時獲取的通道號

3)        獲取配置信息

Hik.NET_DVR_SHOWSTRING_V30 struShowStrCfg = new Hik.NET_DVR_SHOWSTRING_V30();//初始化疊加字符結構體
Int32 size = Marshal.SizeOf(struShowStrCfg);//獲取結構體空間大小
IntPtr ptr = Marshal.AllocHGlobal(size);//設置指針大小
Hik.NET_DVR_GetDVRConfig(_userId, 1030, _channelId, ptr, (UInt32)size, ref dwReturn);//獲取配置信息
struShowStrCfg = (Hik.NET_DVR_SHOWSTRING_V30)Marshal.PtrToStructure(ptr, typeof(Hik.NET_DVR_SHOWSTRING_V30));//指針轉換爲結構體
Marshal.FreeHGlobal(ptr);//釋放指針

4)        疊加字符結構體

NET_DVR_SHOWSTRINGINFO struStringInfo;/* 要顯示的字符內容 */

說明:設置疊加字符需要爲其屬性賦值。

5)        設置配置信息

Hik.NET_DVR_SHOWSTRING_V30 struShowStrCfg =獲取疊加字符配置信息();
Int32 size = Marshal.SizeOf(struShowStrCfg);//獲取結構體空間大小
IntPtr ptr = Marshal.AllocHGlobal(size);//設置指針空間大小
String osd = "海康智能監控視頻一";
struShowStrCfg.struStringInfo[0].wShowString = 1;//1爲顯示,0爲不顯示
struShowStrCfg.struStringInfo[0].sString = osd;//疊加的字符串
struShowStrCfg.struStringInfo[0].wStringSize = (ushort)(osd.Length * 2);//字符串大小
struShowStrCfg.struStringInfo[0].wShowStringTopLeftX = 0;//座標
struShowStrCfg.struStringInfo[0].wShowStringTopLeftY = 0;//座標
Marshal.StructureToPtr(struShowStrCfg, ptr, false);//街頭體轉換爲指針
Hik.NET_DVR_SetDVRConfig(_userId, 1031, _channelId, ptr, (UInt32)size);//設置配置信息
Marshal.FreeHGlobal(ptr);//釋放指針

說明:可以疊加顯示多個字符串。

13.    球機定位速度設置

1)        設備配置命令

3270;//獲取PTZ基本參數信息
3271;//設置PTZ基本參數信息

2)        通道號或者組號

ChannelId//登錄IPC設備時獲取的通道號

3)        獲取配置信息

Hik.NET_DVR_PTZ_BASICPARAMCFG basicParamCfg = new Hik.NET_DVR_PTZ_BASICPARAMCFG();//初始化PTZ基本參數結構體
Int32 size = Marshal.SizeOf(basicParamCfg);//獲取結構體空間大小
IntPtr ptr = Marshal.AllocHGlobal(size);//設置指針大小
Hik.NET_DVR_GetDVRConfig(userId, 3270, _channelId, ptr, (UInt32)size, ref bytesReturned);//獲取配置參數指針
basicParamCfg = (Hik.NET_DVR_PTZ_BASICPARAMCFG)Marshal.PtrToStructure(ptr, typeof(Hik.NET_DVR_PTZ_BASICPARAMCFG));//指針轉換爲結構體
Marshal.FreeHGlobal(ptr);//釋放指針

4)        球機定位速度命令

1-8

5)        球機定位速度結構體

Hik.NET_DVR_PTZ_BASICPARAMCFG basicParamCfg

6)        設置配置信息

Hik.NET_DVR_PTZ_BASICPARAMCFG basicParamCfg = 獲取配置信息();
Int32 size = Marshal.SizeOf(basicParamCfg);//獲取結構體空間大小
IntPtr ptr = Marshal.AllocHGlobal(size);//設置指針空間大小
basicParamCfg.byPresetSpeed = (byte)速度值;
Marshal.StructureToPtr(basicParamCfg, ptr, false);//結構體轉換爲指針
Hik.NET_DVR_SetDVRConfig(userId, 3271, _channelId, ptr, size);//設置配置信息
Marshal.FreeHGlobal(ptr);//釋放指針

14.    獲取球機轉動範圍

1)        設備配置命令

294;//雲臺獲取PTZ範圍

2)        通道號或者組號

ChannelId//登錄IPC設備時獲取的通道號

3)        獲取配置信息

Hik.NET_DVR_PTZSCOPE PTZScope = new Hik.NET_DVR_PTZSCOPE();//初始化球機範圍信息結構體
Int32 size = Marshal.SizeOf(PTZScope);//獲取結構體空間大小
IntPtr ptrScope = Marshal.AllocHGlobal(size);//設置指針空間大小
Hik.NET_DVR_GetDVRConfig(_userId, 294, _channelId, ptrScope, (UInt32)size, ref result);//獲取配置信息
PTZScope = (Hik.NET_DVR_PTZSCOPE)Marshal.PtrToStructure(ptrScope, typeof(Hik.NET_DVR_PTZSCOPE));//指針轉換爲結構體
Marshal.FreeHGlobal(ptrScope);//釋放指針

4)        球機轉動範圍結構體

Hik.NET_DVR_PTZSCOPE PTZScope

15.    球機定位

使用球機定位功能前,需先設置球機定位速度和獲取球機轉動範圍,再根據球機轉動範圍信息來操作球機定位功能。

1)        設備配置命令

292;//雲臺設置PTZ位置
293;//雲臺獲取PTZ位置

2)        通道號或者組號

ChannelId//登錄IPC設備時獲取的通道號

3)        獲取配置信息

//用精簡方式實現
Int32 size = Marshal.SizeOf(typeof(Hik.NET_DVR_PTZPOS));//獲取球機位置信息結構體大小
IntPtr ptrPTZ = Marshal.AllocHGlobal(size);//設置指針空間大小
Hik.NET_DVR_GetDVRConfig(_userId, 293, _channelId, ptrPTZ, (UInt32)size, ref result);//獲取球機位置配置信息
Hik.NET_DVR_PTZPOS PTZPos = (Hik.NET_DVR_PTZPOS)Marshal.PtrToStructure(ptrPTZ, typeof(Hik.NET_DVR_PTZPOS));//指針轉換爲結構體
Marshal.FreeHGlobal(ptrPTZ);//釋放指針

4)        透霧切換結構體

Hik.NET_DVR_PTZPOS PTZPos

5)        設置配置信息

Hik.NET_DVR_PTZPOS PTZPos = 獲取球機位置信息();
Int32 size = Marshal.SizeOf(PTZPos);//獲取結構體空間大小
IntPtr ptr = Marshal.AllocHGlobal(size);//設置指針空間大小
PTZPos.wAction = 1;//-表示定位PTZ參數
//本結構體中的wAction參數是設置時的操作類型,因此獲取時該參數無效。實際顯示的PTZ值是獲取到的十六進制值的十分之一,如獲取的水平參數P的值是0x1750,實際顯示的P值爲175度;獲取到的垂直參數T的值是0x0789,實際顯示的T值爲78.9度;獲取到的變倍參數Z的值是0x1100,實際顯示的Z值爲110度。
String temp = "0x" + Convert.ToString(horAngle * 10);//實際顯示的PTZ值是獲取到的十六進制值的十分之一,所以需要把輸入的數值乘以10再拼成十六進制字符串
PTZPos.wPanPos = Convert.ToUInt16(temp, 16);//轉換爲16進制水平角度
if (pitAngle >= 0)//判斷俯仰角度的正負。由於零方位角的設置不同,會導致出現負的俯仰角度,所以處理方式不同
   PTZPos.wTiltPos = Convert.ToUInt16("0x" + Convert.ToString(pitAngle * 10), 16);
else
   PTZPos.wTiltPos = Convert.ToUInt16("0x" + Convert.ToString((pitAngle + 360) * 10), 16);
PTZPos.wZoomPos = Convert.ToUInt16("0x" + Convert.ToString(viewAngle * 10), 16);
Marshal.StructureToPtr(PTZPos, ptr, false);//結構體轉換爲指針
Hik.NET_DVR_SetDVRConfig(_userId, 292, _channelId, ptr, (uint)size);//設置配置
Marshal.FreeHGlobal(ptr);//釋放指針

16.    零方位角控制

1)        設備配置命令

3283;// 零方位角控制

2)        通道號或者組號

ChannelId//登錄IPC設備時獲取的通道號

3)        零方位角控制命令

SET = 0,//設置
GOTO = 1,//調用
CLE = 2//清除

4)        零方位角控制結構體

Hik.NET_DVR_INITIALPOSITIONCTRL initialPositionCtrl

5)        設置控制信息

Hik.NET_DVR_INITIALPOSITIONCTRL initialPositionCtrl = new Hik.NET_DVR_INITIALPOSITIONCTRL();//初始化零方位角控制結構體
Int32 size = Marshal.SizeOf(initialPositionCtrl);//獲取結構體空間大小
IntPtr ptr = Marshal.AllocHGlobal(size);//設置指針大小
initialPositionCtrl.dwSize = (uint)size;//結構體大小
initialPositionCtrl.dwChan = (uint)_channelId;//播放通道號
initialPositionCtrl.byWorkMode = (byte)command;//零方位角控制命令
Marshal.StructureToPtr(initialPositionCtrl, ptr, false);//結構體轉換爲指針
Hik.NET_DVR_RemoteControl(_userId, (uint)3283, ptr, (uint)size);//零方位角控制
Marshal.FreeHGlobal(ptr);//釋放指針

17.    錄像回放

此功能需要硬盤錄像機支持。需要先登錄NVR設備。在登錄和獲取數字通道號後,根據設備所對應的通道號操作相關IPC設備的一些基礎功能。

1)        設備配置命令

1;//開始播放
2;//停止播放
3;//暫停播放
4;//恢復播放
5;//快放
6;//慢放
7;//正常速度
8;//單幀放
9;//打開聲音
10;//關閉聲音
11;//調節音量
12;//改變文件回放的進度
13;//獲取文件回放的進度
14;//獲取當前已經播放的時間(按文件回放的時候有效)
15;//獲取當前已經播放的幀數(按文件回放的時候有效)
16;//獲取當前播放文件總的幀數(按文件回放的時候有效)
17;//獲取當前播放文件總的時間(按文件回放的時候有效)
20;//丟B幀
24;//設置碼流速度
25;//保持與設備的心跳(如果回調阻塞,建議2秒發送一次)
26;//按絕對時間定位
27;//獲取按時間回放對應時間段內的所有文件的總長度
29;//倒放切換爲正放
30;//正放切換爲倒放
32;//設置轉封裝類型
33;//正放切換爲倒放

2)        初始化錄像回放結構體

Hik.NET_DVR_VOD_PARA struVodPara = new Hik.NET_DVR_VOD_PARA();//初始化錄像回放結構體
struVodPara.dwSize = (uint)Marshal.SizeOf(struVodPara);//獲取結構體空間大小
struVodPara.struIDInfo.dwChannel = (uint)_ipChannelId; //數字通道號 Channel number,海康設備數字通道號從33開始  
//struVodPara.hWnd = this.pictureBoxVideo.Handle;//不使用回調獲取回放視頻時,使用此屬性設置回放窗口句柄
 struVodPara.hWnd = IntPtr.Zero;//使用回調獲取回放視頻時,需如此設置回放窗口句柄
//設置回放的開始時間 Set the starting time to search video files
struVodPara.struBeginTime.dwYear = (uint)dateTimeStart.Value.Year;
struVodPara.struBeginTime.dwMonth = (uint)dateTimeStart.Value.Month;
struVodPara.struBeginTime.dwDay = (uint)dateTimeStart.Value.Day;
struVodPara.struBeginTime.dwHour = (uint)dateTimeStart.Value.Hour;
struVodPara.struBeginTime.dwMinute = (uint)dateTimeStart.Value.Minute;
struVodPara.struBeginTime.dwSecond = (uint)dateTimeStart.Value.Second;
//設置回放的結束時間 Set the stopping time to search video files
struVodPara.struEndTime.dwYear = (uint)dateTimeEnd.Value.Year;
struVodPara.struEndTime.dwMonth = (uint)dateTimeEnd.Value.Month;
struVodPara.struEndTime.dwDay = (uint)dateTimeEnd.Value.Day;
struVodPara.struEndTime.dwHour = (uint)dateTimeEnd.Value.Hour;
struVodPara.struEndTime.dwMinute = (uint)dateTimeEnd.Value.Minute;
struVodPara.struEndTime.dwSecond = (uint)dateTimeEnd.Value.Second;

3)        獲取錄像回放播放句柄

目前根據需求只實現根據錄像起止時間範圍播放錄像視頻,其他功能請參考SDK功能說明文檔。

//按時間回放 Playback by time
_realHandle = Hik.NET_DVR_PlayBackByTime_V40(_NVRUserId, ref struVodPara);// struVodPara爲錄像回放結構體

4)        錄像數據回調函數的使用

/// <summary>
/// 錄像數據回調函數 
/// </summary>
/// <param name="lPlayHandle">當前的錄像播放句柄</param>
/// <param name="dwDataType">數據類型</param>
/// <param name="pBuffer">存放數據的緩衝區指針</param>
/// <param name="dwBufSize">緩衝區大小</param>
/// <param name="pUser">用戶數據</param>
public delegate void PlayDataCallBack_V40(Int32 lPlayHandle, UInt32 dwDataType, IntPtr pBuffer, UInt32 dwBufSize, IntPtr pUser);

此回調函數的使用方式與實時流回調函數的操作方式類似,都是獲取視頻流後,用播放庫解碼,返回角度信息和解碼後的視頻流。

Hik.NET_DVR_PlayBackControl_V40(_realHandle, 1, IntPtr.Zero, 0, IntPtr.Zero, ref iOutValue);//播放錄像回放視頻

5)        停止錄像回放

Hik.NET_DVR_StopPlayBack(_realHandle)

18.    錄像下載

1)        初始化錄像下載結構體

Hik.NET_DVR_PLAYCOND struDownPara = new Hik.NET_DVR_PLAYCOND();//初始化錄像下載結構體
struDownPara.dwChannel = (uint)_ipChannelId; //數字通道號 Channel number  
//設置下載的開始時間 Set the starting time
struDownPara.struStartTime.dwYear = (uint)dateTimeStart.Value.Year;
struDownPara.struStartTime.dwMonth = (uint)dateTimeStart.Value.Month;
struDownPara.struStartTime.dwDay = (uint)dateTimeStart.Value.Day;
struDownPara.struStartTime.dwHour = (uint)dateTimeStart.Value.Hour;
struDownPara.struStartTime.dwMinute = (uint)dateTimeStart.Value.Minute;
struDownPara.struStartTime.dwSecond = (uint)dateTimeStart.Value.Second;
//設置下載的結束時間 Set the stopping time
struDownPara.struStopTime.dwYear = (uint)dateTimeEnd.Value.Year;
struDownPara.struStopTime.dwMonth = (uint)dateTimeEnd.Value.Month;
struDownPara.struStopTime.dwDay = (uint)dateTimeEnd.Value.Day;
struDownPara.struStopTime.dwHour = (uint)dateTimeEnd.Value.Hour;
struDownPara.struStopTime.dwMinute = (uint)dateTimeEnd.Value.Minute;
struDownPara.struStopTime.dwSecond = (uint)dateTimeEnd.Value.Second;

2)        錄像下載結構體

Hik.NET_DVR_PLAYCOND  struDownPara

3)        錄像下載

錄像下載後默認保存格式爲mp4。

_realHandle = Hik.NET_DVR_GetFileByTime_V40(_NVRUserId, sVideoFileName, ref struDownPara);

Plat_SDK編程指南

海康平臺可以掛載多個NVR設備,調用NVR下掛載的IPC設備時,只需要在海康平臺的設備設置中找到其攝像頭ID即可。

(一)    SDK的引用

具體引用方式,參見IPC_SDK的引用。由於海康平臺技術人員提供的DLL文件過於繁雜,就不一一列出DLL的說明,詳情參見IVMS_SDK文件夾目錄。

(二)    C#程序調用DLL中的非託管函數方法

詳情參見C#程序調用DLL中的非託管函數方法

(三)    SDK的調用

根據海康視頻設備及平臺使用的方案設計,只應用海康平臺SDK的視頻回調顯示功能,其它功能暫不使用。對Plat_SDK的C#封裝類見附件HikIVMS.cs,可參考此基礎類文件進行程序功能編寫。

1.        獲取錯誤碼

Plat_GetLastError(_userId);//獲取錯誤碼,userId爲登錄後獲得的用戶ID

使用方式:如果每個非託管函數方法返回結果不爲0(正確),則調用此方法獲取錯誤碼。

例如:

Int32 ret = Plat_Init();
if (ret != 0)
   throw new HikIVMSException(Plat_GetLastError(_userId));// HikIVMSException爲自定義異常調用類,用來解析錯誤碼拋出異常

2.        登錄

1)        用戶註冊

Int32 ret;
ret = Plat_Init();//platformSDK初始化
if (ret != 0)
   throw new HikIVMSException(Plat_GetLastError(_userId));
IntPtr ptrIP = Marshal.StringToHGlobalAnsi(uri.Host);//IP
IntPtr ptrUserName = Marshal.StringToHGlobalAnsi(a[0]);//用戶名
IntPtr ptrPassword = Marshal.StringToHGlobalAnsi(a[1]);//密碼
IntPtr ptrPort = Marshal.StringToHGlobalAnsi(uri.Port.ToString());//端口號
_userId = Plat_LoginCMS(ptrIP, ptrUserName, ptrPassword, ptrPort, 0);//登錄
//釋放指針
Marshal.FreeHGlobal(ptrIP);
Marshal.FreeHGlobal(ptrUserName);
Marshal.FreeHGlobal(ptrPassword);
Marshal.FreeHGlobal(ptrPort);

2)        用戶註銷

//如果存在播放的視頻,也就是_streamHandle播放句柄>0,則先停止播放視頻
Plat_StopVideo(_streamHandle);
Plat_LogoutCMS(_userId);//註銷用戶
Plat_Free();//釋放SDK,必須執行

3.        預覽

1)        播放預覽

/// <summary>
/// 播放實時視頻(開始預覽/回放)
/// </summary>
/// <param name="url">預覽或回放的播放路徑,由Plat_QueryRealStreamURL或Plat_QueryRecordFile</param>
/// <param name="hWnd">播放窗口句柄,如果爲空,則不播放</param>
/// <param name="userHandle">用戶ID</param>
/// <param name="streamCallback">視頻碼流接收回調函數指針,如果回調函數爲NULL則不給碼流</param>
/// <returns>>=0成功,返回實時視頻句柄,錯誤時返回-1</returns>
Int32 Plat_PlayVideo(String url, IntPtr hWnd, Int32 userHandle, fStreamCallback streamCallback, IntPtr user);

例如:

_streamHandle = Plat_PlayVideo(cameraId, IntPtr.Zero, _userId, callback, IntPtr.Zero);

注意:此函數的第一個參數,在應用中只需要傳入攝像機ID即可。

2)        實時流回調函數的使用

/// <summary>
/// 實時流回調
/// </summary>
/// <param name="handle">Plat_PlayVideo返回的句柄</param>
/// <param name="data">接收視頻碼流數據緩衝區指針</param>
/// <param name="size">接收視頻碼流數據字節數</param>
/// <param name="user">用戶數據</param>
public delegate void fStreamCallback(Int32 handle, IntPtr data, UInt32 size, IntPtr user, UInt32 dataType);

其調用方式與IPC_SDK中回調實時視頻流的方式相同,都是調用播放庫解碼,然後返回角度信息和解碼後的視頻。詳情參見IPC_SDK預覽功能說明

示例如下:

private HikIVMS.fStreamCallback _callback;
private HikIVMS.DECCBFUN _displayCallback;//解碼回調
private HikIVMS.ADDITIONDATACBFUN _additionDataDisplayCallback;//角度回調
 
if (_callback == null)
_callback = new HikIVMS.fStreamCallback(StreamCallback);
if (_displayCallback == null)
 _displayCallback = new HikIVMS.DECCBFUN(DecCallbackFUN);
if (_additionDataDisplayCallback == null)
 _additionDataDisplayCallback = new HikIVMS.ADDITIONDATACBFUN(AdditionDataCallBackFUN);
Hik.Play(cameraCode, _callback);

注意:Plat的回調函數與IPC回調函數中唯一的區別在於數據類型的定義不同,IPC的系統頭數據類型爲1,視頻流數據類型爲2;Plat系統頭數據類型爲0,視頻流數據類型爲1,僅此區別,其它相同。

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