一:前言
解码器是用来解码摄像头输出视频的。SDK是异步模式,很多功能都是依靠异步消息驱动。
使用 Marshal.AllocHGlobal、Marshal.FreeHGlobal来分配、释放非托管内存;
使用Marshal.StructureToPtr、Marshal.PtrToStructure来实现对结构体指针的操作;
二:SDK调用顺序
1. 初始化开发包(该SDK版本为Version4.0)
int __stdcall Dec_ClientStartup(unsigned int_uiMessage, HWND _hWnd);
2. 设置开发包需要的一些参数
int __stdcall DEC_ClientSetNotify(DecNotifyFun* _pNotify);
3. 调用开发包所提供的其他函数(连接摄像头预览视频、调整视频等功能函数)
4. 释放开发包
int __stdcall DEC_ClientCleanup();
三:二次开发
1.初始化开发包
C++:
C#:
//结构体写在namespace里,不是类里
//OnParamChangeNotify和OnMainNotfy由系统(ParamChangeNotify/MainNotfy函数)调用,而不是由程序员调用
2.登录解码器
//注册登录函数,注意操作完毕后要记得注销,不然断电后将无法控制解码器
//调用函数。执行完该函数后,会触发OnMainNotify主回调信息函数,可以在OnMainNotify函数里这么写
//为了拿到登录状态(状态在非托管内存中),将信息放到托管的LogonStatus结构体里,使用Marshal.PtrToStructure完成
//NetSDKMsg定义回调消息类型
3:连接摄像头,解码器进行解码
//联合体:需要联合体的哪一个结构体只需定义哪一个结构体,无需定义ServerItem
C#:
//strServerPtzPortocol为动态链接库,和NVDSDK.dll一起放在bin包
//结构体嵌套结构体
//此函数ServerItem参数是一个结构体,具体传哪一种结构体视情况(NormalServer/OnvifServer/RtspServer/EncodeChannel)而定。
//C#定义的NormalServer结构体里放入我们需要传入的数据(摄像头账号密码等信息)使用StructureToPtr将数据放入非托管内存中
3:拼控(2 * 2)
第一步:获取大屏的数量 tDev.iSplitChanNum ,来自方法DEC_ClientGetDevConfig
第二步:获取拼控其实编号 tOffset.iSplitScreen ,来自方法DEC_ClientGetDevConfig,
获取所有拼控大屏可以遍历 拼控起始编号+n 完成。
第三步:创建大屏 DEC_ClientSetDevConfig
// 获取支持的大屏数量,获取拼控的起始编号、开窗起始编号:执行DEC_ClientGetDevConfig后,Marshal.StructureToPtr用来将结构体从托管内存封送到非托管内存,
Marshal.PtrToStructure用来将非托管内存块封送到新分配的托管对象,完成从非托管取数据
//创建大屏,完成向非托管放数据。DEC_ClientSetDevConfig函数结束以后,将 2 * 2 = 4个通道合并成一个虚拟大屏通道
//最后需要执行一次DEC_ClientStartView_V1函数,且将此函数的第二个参数改为拼控起始编号,执行完发现值其实为10000(S5解码器为16),我这里写死。到这里完成拼控