使用大华NetSDK对接相机
一、 下载大华NetSDK
根据自己的需要下载对应版本的sdk。这边我们就以Win32版本作为开发使用。
下载的文件解压后,内部文件如下图所示:
开发使用到的文件在库文件和头文件目录中。使用手册和演示程序则提供了快速上手使用的说明和实例;
二、 使用NetSDK对接大华设备
1、 基本概念
设备发现:
在局域网中寻找大华设备,找到所有接入当前局域网的设备
登录:
我们在操作相机前,必须先登录设备,登录的过程,就是校验用户名密码的过程,和设备校验身份后,才能与设备进行信令交互。
拉流:
获取相机视频流的过程称为拉流,相机上的视频分两种:实时视频,回放视频(录像)
云台:
部分相机拥有云台功能,云台就是一个可调节相机视角的装置,相对于固定镜头相机,云台相机可以通过控制方向,将镜头转向感兴趣的方向,查看感兴趣位置的视频。
2、 开发说明
下面,我用一个简单的控制台demo实现一个登录设备并且拉流的功能,先说明下基本步骤:
1、 包含头文件:
#include "dhnetsdk.h"
2、 指定需要链接的静态库
#pragma comment(lib, "dhnetsdk.lib")
3、初始化,这里我们简单处理,先将不传断线检测回调,后面讲到断线时再提
CLIENT_InitEx(NULL, 0);
4、登录设备,接口返回一个登录句柄,后续对设备的操作接口,均需要使用该句柄
CLIENT_LoginWithHighLevelSecurity(...);
5、调用实时预览接口,返回一个实时预览句柄,后续对本次拉流的操作,均需要带该句柄
CLIENT_RealPlayEx(...)
6、关闭系统前停止拉流,使用步骤5返回的句柄
CLIENT_StopRealPlayEx(...)
7、 登出设备,使用步骤4返回的句柄进行登出
CLIENT_Logout(...);
8、关闭系统前,清理SDK资源
CLIENT_Cleanup();
3、 实例程序
#include <iostream>
#include <string>
#include <string.h>
#include "dhnetsdk.h"
#pragma comment(lib, "dhnetsdk.lib")
// 我们将相机ip等信息通过argv数据传入
int main(int argc, char* argv[])
{
//1、初始化SDK
if (FALSE == CLIENT_InitEx(NULL, 0))
{
std::cout<<"SDK 初始化失败!"<<std::endl;
return -1;
}
//2、 登录设备
std::string strIP = "192.168.1.108";
int nPort = 37777;//大华相机默认通信端口为37777
std::string strUser = "admin";
std::string strPwd = "admin";
if (argc > 1)
{
strIP = argv[1];
}
if (argc > 2)
{
strUser = argv[2];
}
if (argc > 3)
{
strPwd = argv[3];
}
NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY stuInParam = {sizeof(stuInParam)};// 定义登录接口入参结构体,赋值第一个参数为sizeof(stuInParam),PS:第一个参数是dwSzie
stuInParam.emSpecCap = EM_LOGIN_SPEC_CAP_TCP; //使用最普通的TCP方式登录
strcpy(stuInParam.szIP, strIP.c_str());
strcpy(stuInParam.szUserName, strUser.c_str());
strcpy(stuInParam.szPassword, strPwd.c_str());
stuInParam.nPort = nPort;
NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY stuOutParam = {sizeof(stuOutParam)};// 定义登录接口出参结构体
LLONG lLoginID = CLIENT_LoginWithHighLevelSecurity(&stuInParam, &stuOutParam);
if (0 == lLoginID)
{// 登录失败
std::cout<<"Login failed! error:"<<stuOutParam.nError<<std::endl;
}
else
{// 登录成功
std::cout<<"Login success! Device Type:"<<stuOutParam.stuDeviceInfo.nDVRType<<" Channel number:"<< stuOutParam.stuDeviceInfo.nChanNum <<std::endl;
//3、 拉流, 参数二代表通道号,从0开始,0代表拉第一通道的流。hWnd这里也传0,因为我们用控制台,不显示画面。
LLONG lPlayHandle = CLIENT_RealPlayEx(lLoginID, 0, NULL);
if (0 == lPlayHandle)
{
std::cout<<"RealPlay failed! error:"<<CLIENT_GetLastError()<<std::endl;
}
else
{
CLIENT_SaveRealData(lPlayHandle, "test.dav");// 将设备上拉来的码流保存成大华视频文件
system("PAUSE");
if (FALSE == CLIENT_StopRealPlayEx(lPlayHandle)) // 停止拉流
{
std::cout<<"Stop RealPlay failed! error:"<<(int)(0xFFFF&CLIENT_GetLastError())<<std::endl;
}
lPlayHandle = 0;
}
CLIENT_Logout(lLoginID);//登出
lLoginID = 0;
}
// 清理资源
CLIENT_Cleanup();
}
4、 调试
当我们调用接口失败时,需要获取接口失败的原因,这个时候我们可以调用获取最近错误码的接口:
CLIENT_GetLastError();
这个接口的返回值,我们打印时,我们可以用0xFFFF并一下这个返回值再打印,按10进制int型打印,这样,打印的值就是一个正数。然后我们在头文件匹配错误码
#define NET_NOERROR 0 // 没有错误
#define NET_ERROR -1 // 未知错误
#define NET_SYSTEM_ERROR _EC(1) // 系统出错
#define NET_NETWORK_ERROR _EC(2) // 网络错误,可能是因为网络超时
#define NET_DEV_VER_NOMATCH _EC(3) // 设备协议不匹配
#define NET_INVALID_HANDLE _EC(4) // 句柄无效
更多错误码请到头文件中去匹配