前言
近一个星期在写服务器端,一直没有成功,就没有继续往下写文章,可喜的是这一局面在今天下午得到改变(客户端已经能够连接我自己写的服务器端了!),顺便说下客户端大概2-3篇文章,接下来就会写关于服务器的文章了,感谢关注,也希望能帮助得到你: )
推荐文章
1. C# 与 C++ 数据类型对照 ,极其推荐!!调用VC++的dll最主要的问题之一就是数据类型对应了!!
2. 压缩卡及硬盘录像机常见故障集锦,里面有很多关于视频方面的知识。
3. 大城小格 ,他的博客上有系列文章,虽然简短,仍有很多帮助!
4. 杭州海康威视数字技术有限公司-疑难解答|常见问题|FAQ
注意
本系列文章限于学习交流,注重过程,由于涉及公司,所以不提供源代码下载,非常抱歉!!但是请大家放心,核心、实现以及其他能够贴出来的代码我都会贴出来,并且争取尽所能的回答评论里的每一个问题,感谢大家关注,欢迎交流 :)
系列
1. C# 视频监控系列(1):准备
2. C# 视频监控系列(2):客户端——封装API
3. C# 视频监控系列(3):客户端——连接服务器
正文
1. 将以下四个dll拷贝到system32目录下,这几个文件均在根目录的Bin目录下
DS40xxSDK.dll
hikclient.dll
HikPlayM4.dll
HikServer.dll
2. 先用自带的客户端Net Client Demo(Soft Decdoe)运行下确认没有问题再根据VC++客户端的例子写对应的C#代码。
3. 最好装一个Microsoft Visual C++ 6.0,这样能把VC++的例子跑起来并调试。注意他是Win32 Release的,需要切换至Win32 Debug模式才能断点调试!!
4. 打开API文档Hikvision 板卡网络开发包编程手册V4.7,在Doc目录下。
5. 代码分析和编写对应的C#代码
5.1 第二章编程说明中第六条我们可以看到API依次调用的顺序,可以根据函数名直接在代码中搜索调用顺序,不难发现,在HKVisionDlg.cpp的OnInitDialog方法能看到如下两行代码:
MP4_ClientSetNetPort(
5050
,
6050
);
MP4_ClientStartup(WM_MYCOMMAND,
this
->
m_hWnd);
很明显这是调用了API,其他代码就不用管了,那么我把这代码翻译到C# WinForm的Form1_Load事件里面,并且也这样调用API(封装好的SDK请看上篇文章):
PcHikClient.MP4_ClientSetNetPort(
5050
,
6050
);
PcHikClient.MP4_ClientStartup(PcHikClient.WM_USER
+
1
,
this
.Handle);
5.2 根据界面上Start按钮事件能找到关键的连接上服务器,如下:
if
(m_showmode
==
0
)
{
MP4_ClientSetShowMode(NORMALMODE,
0
);
}
else
{
MP4_ClientSetShowMode(OVERLAYMODE,COLORREF(
0xff00ff
));
}
nn1
=
nn2
=
nn3
=
nn4
=
-
1
;
int
itemp
=
m_shownum;
char
ips[
256
];
sprintf(ips,
"
%s
"
,m_ipadd);
hWnd5
=
m_video5.GetSafeHwnd();
//
aa5.m_bRemoteChannel
=
0
;
switch
(m_linktype)
{
case
0
:
aa5.m_bSendMode
=
TCPMODE;
break
;
case
1
:
aa5.m_bSendMode
=
UDPMODE;
break
;
case
2
:
aa5.m_bSendMode
=
MULTIMODE;
break
;
case
3
:
aa5.m_bSendMode
=
DIALING;
break
;
case
4
:
aa5.m_bSendMode
=
AUDIODETACH;
break
;
default
:
aa5.m_bSendMode
=
TCPMODE;
break
;
}
aa5.m_sIPAddress
=
ips;
//
2003.12.2
//
如果想只录像,而不进行解码,可以将m_hShowVideo设置成NULL
//
If you just want to record without decode on client side,
//
please set m_hShowVideo as NULL
#if
defined RECORD_ONLY
aa5.m_hShowVideo
=
NULL;
#else
aa5.m_hShowVideo
=
hWnd5;
#endif
//
add 2003.12.2
//
m_nImgFormat 指明想要获取的图像格式
//
依赖服务器端的设置。如果不设置,获取的是服务器的缺省格式
//
m_nImgFormat indicates the picture format you get on the client side,
//
It depends on the setting of Server side.
aa5.m_nImgFormat
=
0
;
//
request CIF format
//
aa5.m_nImgFormat = 1;
//
request QCIF format
aa5.m_sUserName
=
"
123
"
;
aa5.m_sUserPassword
=
"
w
"
;
aa5.m_bUserCheck
=
TRUE;
MP4_ClientSetTTL(
64
);
nn1
=
MP4_ClientStart(
&
aa5,ReadDataCallBack);
if
(nn1
==
-
1
)
{
MessageBox(
"
error
"
);
return
;
}
//
BOOL breturn;
breturn
=
MP4_ClientRigisterDrawFun(nn1,DrawFun,
0
);
switch
(m_delaytype)
{
case
0
:
MP4_ClientSetBufferNum(nn1,
40
);
MP4_ClientSetPlayDelay(nn1,
580
);
break
;
case
1
:
MP4_ClientSetBufferNum(nn1,
15
);
MP4_ClientSetPlayDelay(nn1,
40
);
break
;
case
2
:
MP4_ClientSetBufferNum(nn1,
15
);
MP4_ClientSetPlayDelay(nn1,
0
);
break
;
case
3
:
MP4_ClientSetBufferNum(nn1,
0
);
MP4_ClientSetPlayDelay(nn1,
0
);
break
;
}
//
MP4_ClientThrowBFrame(nn1,m_bframenum);
MP4_ClientSetCapPicCallBack(nn1,CapPicFun);
有VC++代码可以看得出来接下来代码都和这差不多,应该就是初始化显示四个窗口的代码了,那我们就不需要把这个方法里面的代码全部翻译了,只需要达到连接一个视频窗口的目的就可以了,翻译的过程中可以自己先临时设置一些变量来让代码跑起来,翻译过程中每次都执行到MP4_ClientRigisterDrawFun方法的时候就报错了,但是画面确已经出来了,所有我就从这里截断了,先达到目的再说,请看翻译对象的C#代码:
int
cs;
private
void
button1_Click(
object
sender, EventArgs e)
{
CLIENT_VIDEOINFO cVideo
=
new
CLIENT_VIDEOINFO();
//
对应服务端通道号
cVideo.m_bRemoteChannel
=
(
byte
)
0
;
//
网络连接模式
cVideo.m_bSendMode
=
(
byte
)SEND_MODE.TCPMODE;
//
服务端IP地址
cVideo.m_sIPAddress
=
"
192.168.0.188"
;
//
显示区域
cVideo.m_hShowVideo
=
pVideo.Handle;
//
(IntPtr)null;
//
图像格式
cVideo.m_nImgFormat
=
(
byte
)
0
;
//
用户名
cVideo.m_sUserName
=
"
123
"
;
//
密码
cVideo.m_sUserPassword
=
"
w
"
;
//
是否需要发生密码
cVideo.m_bUserCheck
=
true
;
//
设置多播的TTL参数
PcHikClient.MP4_ClientSetTTL((
char
)
64
);
//
启动客户端
cs
=
PcHikClient.MP4_ClientStart(
ref
cVideo,
new
ReadDataCallBack(MyRealDataCallBack1));
}
private
void
MyRealDataCallBack1(
ulong
port, [MarshalAs(UnmanagedType.LPArray)]
byte
[] pBuffer,
ulong
pSize)
{
MessageBox.Show(pBuffer.Length.ToString());
}
需要注意的是,VC++里面的指针类型,如HWND一般可以对应C#里面的IntPtr数据类型,ReadDataCallBack是回调函数,但是没有执行,不过至此画面已经能够显示出来!!
那么接下来做画面切割,右键事件什么的都只需要你WinForm的开发经验了,我是用的四个面板(Panel)切换隐藏显示的;pVideo是Panel控件;用户名和密码随便设置也能连得上。
5.3 关闭连接
同样找到VC++代码:
if
(nn1
>=
0
)
{
MP4_ClientStopCapture(nn1);
MP4_ClientStop(nn1);
}
对应C#代码:
private
void
Close()
{
PcHikClient.MP4_ClientStopCapture(cs);
PcHikClient.MP4_ClientStop(cs);
pVideo.Invalidate(
true
);
}
需要注意的是这个cs变量,在连接的时候MP4_ClientStart返回值,需要拿全局变量保存起来,以便这里关闭的时候需要,从API文章里面我们也能看到这样的说明。这段代码最好在窗体关闭的时候也加上!!
注意
摘抄:
DS400xM/DS400xH卡在客户端机器运行的要求 主要是针对运行客户端程序的计算机 显卡有要求,需支持Overlay功能,目前主流的显卡nvidia,ati,Intel845GL集成的系列都支持Overlay功能。
在PIII 833的计算机上,可以比较流畅的软解码4路普通的实时图象;在PIV 2G的计算机上,可以比较流畅的软解码8-9路普通的实时图象;如果用我们公司的硬解码卡,只要显卡支持Overlay功能,就可以支持最多达24路的实时图象,并且支持VideoOut功能,可以上电视墙。
结束
如果本文能带你实现预览的功能,将使你信心百倍,效果才是最有说服力的,并祝你好运: )