前言
写系列文章的时候[前言]部分变得无言了,可能来得顺利了点吧: ) 本章中提供的封装均是我用笨办法从<<Hikvision 板卡网络开发包编程手册V4.7>>和<<DS-4000HC、HCS、HC+、HF、HS、MD卡的Windows编程指南V4.3>>中拷贝出来并参照VC++代码进行整理的,主要是针对HikServer.dll和DS40xxSDK.dll的调用封装。
注意
本系列文章限于学习交流,注重过程,由于涉及公司,所以不提供源代码下载,非常抱歉!!但是请大家放心,核心、实现以及其他能够贴出来的代码我都会贴出来,并且争取尽所能的回答留言里的每一个问题,感谢大家关注,欢迎交流 :)
系列
1. C# 视频监控系列(1):准备
2. C# 视频监控系列(2):客户端——封装API
3. C# 视频监控系列(3):客户端——连接服务器
4. C# 视频监控系列(4):客户端——音频接收和抓图
5. C# 视频监控系列(5):客户端——给服务器端发送字符串和录像(数据捕获)
6. C# 视频监控系列(6):服务器端——封装API(上) [HikServer.dll]
正文
1. HikServer.dll
using
System;
using
System.Collections.Generic;
using
System.Text;
using
System.Runtime.InteropServices;
namespace
HikServer
{
public
struct
PSERVER_VIDEOINFO
{
///
<summary>
///
序列号
///
BYTE m_datatype[64];
///
</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst
=
64
)]
public
byte
[] m_datatype;
///
<summary>
///
系统的通道个数
///
BYTE m_channum;
///
</summary>
public
byte
m_channum;
///
<summary>
///
超时等待时间,1-300单位:分钟
///
DWORD m_waittime;
///
</summary>
public
int
m_waittime;
///
<summary>
///
目前没有使用
///
DWORD m_bufnum;
///
</summary>
public
ulong
m_bufnum;
}
//
[StructLayout(LayoutKind.Sequential)]
//
public struct PSERVER_VIDEOINFO
//
{
//
public IntPtr m_datatype;
//
序列号
//
public byte m_channum;
//
系统的通道个数
//
public int m_waittime;
//
超时等待时间,1-300单位:分钟
//
public int m_bufnum;
//
目前没有使用
//
}
///
<summary>
///
通道数据类型
///
</summary>
public
enum
ChannelDataType
{
NORMAL
=
50
,
DIALING,
SMALLPIC
}
///
<summary>
///
VC++Demo:委托内调用SetIBPMode(ChannelHandle[port],211,2,2,framerat);
///
</summary>
///
<param name="port"></param>
///
<param name="framerat"></param>
public
delegate
void
SetIBP(
int
port,
int
framerat);
///
<summary>
///
VC++Demo:委托内调用CaptureIFrame(ChannelHandle[port]);
///
</summary>
///
<param name="port"></param>
public
delegate
void
MakeIFrame(
int
port);
///
<summary>
///
VC++Demo:委托内调用StartVideoCapture(ChannelHandle[port]);
///
</summary>
///
<param name="nChannel"></param>
public
delegate
void
StartCap(
int
nChannel);
///
<summary>
///
VC++Demo:委托内调用StopVideoCapture(ChannelHandle[port]);
///
</summary>
///
<param name="nChannel"></param>
public
delegate
void
StopCap(
int
nChannel);
///
<summary>
///
验证用户名密码
///
</summary>
///
<param name="username"></param>
///
<param name="namelen"></param>
///
<param name="password"></param>
///
<param name="passlen"></param>
///
<returns></returns>
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public
delegate
int
CheckPassword(
string
username,
ushort
namelen,
string
password,
ushort
passlen);
///
<summary>
///
验证IP
///
VC++Demo:return 0;
///
</summary>
///
<param name="nChannel"></param>
///
<param name="nIP"></param>
///
<returns></returns>
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public
delegate
int
CheckIP(
int
nChannel,
string
nIP);
public
static
class
HikServer
{
public
static
readonly
uint
WM_USER
=
0x0400
;
///
<summary>
///
启动服务端
///
返回true表示成功,返回false表示失败
///
<code>
///
BOOL __stdcall MP4_ServerStart(PSERVER_VIDEOINFO videoinfo);
///
</code>
///
</summary>
///
<param name="videoinfo"></param>
///
<returns></returns>
[DllImport(
"
HikServer.dll
"
)]
public
static
extern
int
MP4_ServerStart(
ref
PSERVER_VIDEOINFO videoinfo);
///
<summary>
///
停止服务端
///
返回true表示成功,返回false表示失败
///
<code>
///
BOOL __stdcall MP4_ServerStop();
///
</code>
///
</summary>
///
<returns></returns>
[DllImport(
"
HikServer.dll
"
)]
public
static
extern
bool
MP4_ServerStop();
///
<summary>
///
获取服务器状态
///
返回true表示服务器已经启动,返回false表示服务器没有启动
///
<code>
///
BOOL __stdcall MP4_ServerGetState(WORD * clientnum);
///
typedef unsigned short WORD;
///
</code>
///
</summary>
///
<param name="clientnum">
表示当前与服务器相连的客户端数据
</param>
///
<returns></returns>
[DllImport(
"
HikServer.dll
"
)]
public
static
extern
bool
MP4_ServerGetState(
out
ushort
clientnum);
///
<summary>
///
给客户端发送命令码
///
和函数MP4_ServerStringToClient不同,它给正连接在该通道上的所有客户端发送命令码。
///
返回true表示成功,返回false表示失败
///
<code>
///
BOOL __stdcall MP4_ServerCommandToClient(char cCommand,char nChannel);
///
</code>
///
</summary>
///
<param name="cCommand">
命令码
</param>
///
<param name="nChannel">
通道号
</param>
[DllImport(
"
HikServer.dll
"
)]
public
static
extern
void
MP4_ServerCommandToClient(
int
cCommand,
int
nChannel);
///
<summary>
///
设置接收命令码的相关参数
///
<code>
///
void __stdcall MP4_ServerSetMessage(UINT nMessage,HWND hWnd);
///
</code>
///
</summary>
///
<param name="nMessage">
对应接收程序的消息
</param>
///
<param name="hWnd">
应用程序窗口句柄
</param>
[DllImport(
"
HikServer.dll
"
)]
public
static
extern
void
MP4_ServerSetMessage(
uint
nMessage, IntPtr hWnd);
///
<summary>
///
设置是否进行IP验证。
///
如果进行IP验证,调用该函数,那么每次客户端连接的时候,会调用CheckIP。
///
如果不进行IP验证,不需要调用该函数。
///
如果调用了MP4_ServerCheckIP之后,又想取消IP验证,只需要调用MP4_ServerCheckIP(NULL)。
///
<code>
///
void __stdcall MP4_ServerCheckIP(int(CALLBACK *CheckIP)(DWORD nChannel,char* nIP));
///
CheckIP函数说明:nChannel表示通道号,nIP表示客户端的IP地址。返回0表示验证通过,返回-1
///
表示验证没有通过。
///
</code>
///
</summary>
[DllImport(
"
HikServer.dll
"
)]
public
static
extern
void
MP4_ServerCheckIP(CheckIP cip);
///
<summary>
///
设置是否进行用户身份验证。
///
使用同MP4_ServerCheckIP。
///
目前namelen和password两个值无效,都是50,并不表示用户名和密码的实际长度。用户名和密码必须小于50个字节。
///
说明:
///
1>因为开发包对用户名和密码不做任何处理,只是简单地分别发送50字节的数据到服务端,所以在验证
///
的实现过程中,用户可以通过设置标志位的方法来确定用户名和密码的实际长度。
///
2>也可以同时进行IP验证和用户身份验证。在开发包中先进行用户身份验证,再进行IP验证。
///
<code>
///
7. void __stdcall MP4_ServerCheckPassword(int(CALLBACK *CheckPassword)(char *username,WORD namelen,char *password,WORD passlen));
///
CheckPassword函数说明:username表示用户名,namelen表示用户名字符串长度,password表示密码,passlen表示密码字符串长度。
///
</code>
///
</summary>
///
<param name="nMessage"></param>
///
<param name="hWnd"></param>
[DllImport(
"
HikServer.dll
"
)]
public
static
extern
void
MP4_ServerCheckPassword(CheckPassword cp);
///
<summary>
///
往发送缓存写数据。
///
网络开发包通过这个接口获得板卡的数据。
///
说明:
///
现在开发包内部不会直接调用StartVideoCapture和StopVideoCapture函数,而是通过StartCap和StopCap
///
来启动和停止捕获数据。如果用户调用StopVideoCapture或者停止调用MP4_ServerWriteData都会使客户
///
端无法收到数据。
///
<code>
///
8. void __stdcall MP4_ServerWriteData(DWORD nChannel,UCHAR *pPacketBuffer, DWORD nPacketSize, int frameType, int breakable);
///
typedef unsigned long DWORD;
///
typedef unsigned char UCHAR;
///
</code>
///
</summary>
///
<param name="nChannel">
通道号。
</param>
///
<param name="pPacketBuffer">
缓冲区指针。
</param>
///
<param name="nPacketSize">
缓冲区长度。
</param>
///
<param name="frameType">
帧类型。
</param>
///
<param name="breakable">
ReadStreamData的返回值
</param>
[DllImport(
"
HikServer.dll
"
)]
public
static
extern
void
MP4_ServerWriteData(
ulong
nChannel,
string
pPacketBuffer,
ulong
nPacketSize,
int
frameType,
int
breakable);
///
<summary>
///
设置启动捕获的回调。
///
<code>
///
9. void __stdcall MP4_ServerSetStart(void(CALLBACK *StartCap)(int nChannel));
///
StartCap函数说明:用户实现这个函数,只需要调用StartVideoCapture。
///
nChannel表示通道号。
///
</code>
///
</summary>
///
<param name="sc"></param>
[DllImport(
"
HikServer.dll
"
)]
public
static
extern
void
MP4_ServerSetStart(StartCap sc);
///
<summary>
///
设置停止捕获的回调。
///
<code>
///
10. void __stdcall MP4_ServerSetStop(void(CALLBACK *StopCap)(int nChannel));
///
StopCap函数说明:用户实现这个函数,只需要调用StopVideoCapture。
///
nChannel表示通道号。
///
</code>
///
</summary>
///
<param name="sc"></param>
[DllImport(
"
HikServer.dll
"
)]
public
static
extern
void
MP4_ServerSetStop(StopCap sc);
///
<summary>
///
读取客户端消息。
///
读取客户端MP4_ClientCommandtoServer函数发送过来的消息(不超过900字节),消息的内容和长度由用户自己定义。
///
<code>
///
11. void __stdcall MP4_ServerReadLastMessage(char *m_sIP,char *m_sCommand,WORD *m_wLen);
///
</code>
///
</summary>
///
<param name="m_sIP">
消息来自哪个IP地址
</param>
///
<param name="m_sCommand">
消息缓冲区指针。
</param>
///
<param name="m_wLen">
消息实际长度。
</param>
[DllImport(
"
HikServer.dll
"
)]
public
static
extern
void
MP4_ServerReadLastMessage(StringBuilder m_sIP, StringBuilder m_sCommand,
out
ushort
m_wLen);
///
<summary>
///
给客户端发送消息字符串。
///
<code>
///
12. BOOL __stdcall MP4_ServerStringToClient(LPCTSTR m_lAddrIP,char *m_sCommand, WORD m_wLen);
///
typedef LPCSTR LPCTSTR;
///
typedef CONST CHAR *LPCSTR
///
</code>
///
</summary>
///
<param name="m_lAddrIP">
客户端IP地址。
</param>
///
<param name="m_sCommand">
消息缓冲区指针。
</param>
///
<param name="m_wLen">
消息实际长度。
</param>
///
<returns>
返回TRUE表示成功,返回FALSE表示失败
</returns>
[DllImport(
"
HikServer.dll
"
)]
public
static
extern
bool
MP4_ServerStringToClient(
string
m_lAddrIP,
string
m_sCommand,
ushort
m_wLen);
///
<summary>
///
对nChannel通道的网络连接进行复位。
///
如果需要单独终止该通道目前的客户端连接,或者该通道目前的网络状态处于异常状况,都可以调用该函
///
数。该函数对任何板卡SDK对应操作都不会有任何影响。
///
<code>
///
13. void __stdcall MP4_ServerResetChannel(DWORD nChannel);
///
</code>
///
</summary>
///
<param name="nChannel">
通道号。
</param>
[DllImport(
"
HikServer.dll
"
)]
public
static
extern
void
MP4_ServerResetChannel(
ulong
nChannel);
///
<summary>
///
设置服务端的网络端口号和客户端的网络端口号。
///
服务端使用端口如下(假设dServerPort=5050):
///
TCP只需要占用5050。
///
UDP和多播需要占用5050、5060----(5060+2*通道个数)。
///
///
客户端使用端口如下(假设dClientPort =6050):
///
TCP和多播只需要占用6057。
///
UDP需要占用6057、6060----(6060+2*窗口个数)。
///
<code>
///
14. BOOL __stdcall MP4_ServerSetNetPort(WORD dServerPort,WORD dClientPort);
///
</code>
///
</summary>
///
<param name="dServerPort">
服务端的起始网络端口号。必须和函数MP4_ClientSetNetPort的dServerPort参数相同。
</param>
///
<param name="dClientPort">
客户端的网络端口号。必须和函数MP4_ClientSetNetPort的dClientPort参数相同。
</param>
///
<returns>
返回TRUE表示成功,返回FALSE表示失败。
</returns>
[DllImport(
"
HikServer.dll
"
)]
public
static
extern
int
MP4_ServerSetNetPort(
ushort
dServerPort,
ushort
dClientPort);
///
<summary>
///
设置多播的TTL参数。
///
注意: 如果您不调用函数MP4_ServerSetTTL,默认TTL值是32。
///
MP4_ServerSetTTL设置的值在MP4_ServerStop之后会失效,恢复成默认的32,所以您如果需要指定TTL
///
大小,每次在MP4_ServerStart之前都需要调用MP4_ServerSetTTL。
///
<code>
///
15. BOOL __stdcall MP4_ServerSetTTL(unsigned char cTTLVal);
///
</code>
///
</summary>
///
<param name="cTTLVal">
TTL值。1-255。
</param>
///
<returns>
返回TRUE表示成功,返回FALSE表示失败。
</returns>
[DllImport(
"
HikServer.dll
"
)]
public
static
extern
int
MP4_ServerSetTTL(
byte
cTTLVal);
///
<summary>
///
设置发送缓冲区大小。
///
注意: 如果您不调用函数MP4_ServerSetBufNum,默认缓冲区是30。
///
MP4_ServerSetBufNum设置的值在MP4_ServerStop之后会失效,恢复成默认的30,所以您如果需要指定
///
缓冲区大小,每次在MP4_ServerStart之前都需要调用MP4_ServerSetBufNum。
///
<code>
///
16. BOOL __stdcall MP4_ServerSetBufNum(DWORD nChannel,WORD dBufNum);
///
</code>
///
</summary>
///
<param name="nChannel">
通道号。
</param>
///
<param name="dBufNum">
缓冲区大小。单位是8K,如果dBufNum=10,那么缓冲区大小为80K,建议设置成30。范围:10-100。
</param>
///
<returns>
返回TRUE表示成功,返回FALSE表示失败。
</returns>
[DllImport(
"
HikServer.dll
"
)]
public
static
extern
int
MP4_ServerSetBufNum(
ushort
nChannel,
ushort
dBufNum);
///
<summary>
///
设置自动调节帧率的回调函数,只在电话线连接中使用。
///
在回调函数SetIBP中只调用SetIBPMode函数
///
<code>
///
17. void __stdcall MP4_ServerSetIBPMode(void(CALLBACK *SetIBP)(int nChannel,int framerat));
///
</code>
///
</summary>
///
<param name="setIBP"></param>
[DllImport(
"
HikServer.dll
"
)]
public
static
extern
void
MP4_ServerSetIBPMode(SetIBP setIBP);
///
<summary>
///
设置连接客户端的等待时间和尝试次数。
///
说明:当服务端给客户端发送消息的时候,需要等待客户端应答,以保证客户端收到消息,如果失败,还
///
可以继续尝试dTrynum-1次发送。
///
注意:
///
1>如果这两个参数设得太小,当网络繁忙或客户端繁忙的时候,可能会导致发送消息失败;如果这两个参
///
数设得太大,当试图连接的客户端不存在(IP地址错误、或者关机、或者没有启动客户端软件),消息发送
///
函数会等待很久才返回。
///
2>这两个参数设置之后一直有效,直到下次调用该函数修改。
///
<code>
///
18. BOOL __stdcall MP4_ServerSetWait(DWORD dEachWaitTime,DWORD dTrynum);
///
</code>
///
</summary>
///
<param name="dEachWaitTime">
等待时间。单位是毫秒,范围300-10000。如果不调用这个函数,默认是2000。
</param>
///
<param name="dTrynum">
尝试次数。范围1-50。如果不调用这个函数,默认是2次。
</param>
///
<returns>
返回TRUE表示成功,返回FALSE表示失败。
</returns>
[DllImport(
"
HikServer.dll
"
)]
public
static
extern
bool
MP4_ServerSetWait(
ulong
dEachWaitTime,
ulong
dTrynum);
///
<summary>
///
给连接在指定通道上的所有客户端发送消息字符串。
///
<code>
///
19. BOOL __stdcall MP4_ServerStringToClient_other (char nChannel,char *m_sCommand, WORD m_wLen);
///
</code>
///
</summary>
///
<param name="nChannel">
通道号。
</param>
///
<param name="m_sCommand">
消息缓冲区指针。
</param>
///
<param name="m_wLen">
消息实际长度。
</param>
///
<returns>
返回TRUE表示成功,返回FALSE表示失败。
</returns>
[DllImport(
"
HikServer.dll
"
)]
public
static
extern
bool
MP4_ServerStringToClient_other(
int
nChannel,
string
m_sCommand,
ushort
m_wLen);
///
<summary>
///
动态切换通道数据类型。
///
注意:调用MP4_ServerChangeChanType之前必须调用StopVideoCapture。(详见DEMO)
///
<code>
///
20. BOOL __stdcall MP4_ServerChangeChanType(char nChannel,char cType);
///
</code>
///
</summary>
///
<param name="nChannel">
通道号。
</param>
///
<param name="cType">
通道数据类型,是否支持电话线连接(NORMAL或者DIALING)
</param>
///
<returns>
返回TRUE表示成功,返回FALSE表示失败。
</returns>
[DllImport(
"
HikServer.dll
"
)]
public
static
extern
bool
MP4_ServerChangeChanType(
char
nChannel,
char
cType);
///
<summary>
///
设置回调,重新生成一个I帧。
///
<code>
///
21. void __stdcall MP4_ServerSetCapIFrame(void(CALLBACK *MakeIFrame) (int port));
///
</code>
///
</summary>
///
<param name="mf"></param>
[DllImport(
"
HikServer.dll
"
)]
public
static
extern
void
MP4_ServerSetCapIFrame(MakeIFrame mf);
///
<summary>
///
获取版本号。
///
<code>
///
22. DWORD __stdcall MP4_ServerGetSdkVersion();
///
</code>
///
</summary>
///
<returns></returns>
[DllImport(
"
HikServer.dll
"
)]
public
static
extern
ulong
MP4_ServerGetSdkVersion();
///
<summary>
///
设置每个通道的多播组地址和网络端口号。
///
说明:
///
1>目前的多播组采用了两种方式:一是开发包内部分配,用户不需要考虑多播组参数细节,默认采用这种
///
方式;另一种是调用MP4_ServerCastGroup设置多播组参数。
///
2>用户可以通过MP4_ServerCastGroup修改参数bSet,在两种方式之间做切换。
///
每个多播组会占用wPort开始的4个端口。
///
<code>
///
23. BOOL __stdcall MP4_ServerCastGroup(BOOL bSet,DWORD dChannel, char *sIP, WORD wPort);
///
</code>
///
</summary>
///
<param name="bSet">
是否使用自定义的多播组地址和网络端口号。TRUE表示使用,FALSE表示仍然沿用开发包内部自动分配的多播地址和网络端口号。
</param>
///
<param name="dChannel">
通道号。每个通道号对应的多播组地址和网络端口号都是单独设置的。
</param>
///
<param name="sIP">
多播组地址。
</param>
///
<param name="wPort">
多播组网络端口号
</param>
///
<returns>
返回TRUE表示成功,返回FALSE表示失败。
</returns>
[DllImport(
"
HikServer.dll
"
)]
public
static
extern
bool
MP4_ServerCastGroup(
bool
bSet,
ulong
dChannel,
string
sIP,
ushort
wPort);
///
<summary>
///
设置每个通道的最大用户数量。
///
<code>
///
24. BOOL __stdcall MP4_ServerMaxUser(DWORD dwChannel,int nMaxNum)
///
</code>
///
</summary>
///
<param name="dwChannel">
通道号。
</param>
///
<param name="nMaxNum">
用户数量。
</param>
///
<returns>
返回TRUE表示成功,返回FALSE表示失败。
</returns>
[DllImport(
"
HikServer.dll
"
)]
public
static
extern
int
MP4_ServerMaxUser(
uint
dwChannel,
int
nMaxNum);
///
<summary>
///
往发送缓存写数据。网络开发包通过这个接口获得板卡的数据。
///
说明:
///
现在开发包内部不会直接调用StartVideoCapture和StopVideoCapture函数,而是通过StartCap
///
和StopCap来启动和停止捕获数据。如果用户调用StopVideoCapture或者停止调用MP4_ServerWriteDataEx
///
都会使客户端无法收到数据。原来的MP4_ServerWriteData内部调用MP4_ServerWriteDataEx完成相关功能。
///
<code>
///
25. void __stdcall MP4_ServerWriteDataEx(DWORD nPort,UCHAR *pPacketBuffer,DWORD nPacketSize,int frameType,int breakable,int nImgFormat)
///
</code>
///
</summary>
///
<param name="nPort">
通道号。
</param>
///
<param name="pPacketBuffer">
缓冲区指针。
</param>
///
<param name="nPacketSize">
缓冲区长度。
</param>
///
<param name="frameType">
帧类型。
</param>
///
<param name="breakable">
ReadStreamData的返回值
</param>
///
<param name="nImgFormat">
///
图像格式。nImgFormat 为0 时表示发送主通道的音视频数据
///
nImgFormat 为1 时表示发送子通道的音视频数据。
///
</param>
[DllImport(
"
HikServer.dll
"
)]
//
public unsafe static extern void MP4_ServerWriteDataEx(uint nPort, void* pPacketBuffer, uint nPacketSize, int frameType, int breakable, int nImgFormat);
public
static
extern
void
MP4_ServerWriteDataEx(
int
nPort, IntPtr pPacketBuffer,
int
nPacketSize,
int
frameType,
int
breakable,
int
nImgFormat);
//
public static extern void MP4_ServerWriteDataEx(uint nPort, byte[] pPacketBuffer, uint nPacketSize, int frameType, int breakable, int nImgFormat);
}
}
修改记录
1. 2009-8-19,修改了MP4_ServerReadLastMessage,非常感谢 阿斯顿啊 的贡献!
修正前:public static extern void MP4_ServerReadLastMessage(string m_sIP, string m_sCommand, out ushort m_wLen);
修正后:public static extern void MP4_ServerReadLastMessage(StringBuilder m_sIP, StringBuilder m_sCommand, out ushort m_wLen);
结束
在后续的文章中本文中API仍然可能会变动,毕竟我们用的只是其中的一部分,我会随时更新,感谢继续关注。本来是作为一篇文章发布的,发现代码过长,插入都费老半天,所有拆开成上下了!!