使用QT对接大华网络摄像头SDK的示例程序(建议收藏)

    技术2022-07-11  146

    初始化

    大华网络摄像头的默认 IP 地址都是 192.168.1.108,首先将你的电脑和摄像头连接到同一个路由器下,假如你的路由器不是1网段,则对路由器进行设置。 然后在 IE 浏览器下输入192.168.1.108,并参考说明书对摄像头进行配置,用户名,密码等。

    SDK库文件添加

    到大华官网下载最新的 SDK 开发包, 下载地址:大华设备网络SDK

    或者从这儿下载:https://download.csdn.net/download/u012534831/12567061

    下载后解压出库文件和头文件

    使用 QTCreator 新建项目,将头文件放到项目的代码目录,将库文件里面的 dll 放到生成的 exe 目录,将演示程序中的 .lib库放到代码目录,并在 qmake 中引用:

    SOURCES += \ main.cpp \ widget.cpp HEADERS += \ widget.h \ avglobal.h \ dhconfigsdk.h \ dhnetsdk.h LIBS += "C:\Users\HiWin10\Desktop\DH-RealPlay\DH-Realplay-1\lib\dhconfigsdk.lib" LIBS += "C:\Users\HiWin10\Desktop\DH-RealPlay\DH-Realplay-1\lib\dhnetsdk.lib"

    摄像头初始化

    if(CLIENT_Init((fDisConnect)DisConnectFunc, (LDWORD)0)) { cout<<"SDK INIT OK!"<<endl; } else { cout<<"SDK INIT FAIL!"<<endl; }

    摄像头初始化需要传入一个断开连接的回调函数

    //断线回调 void CALLBACK Widget::DisConnectFunc(LLONG lLoginID, char *pchDVRIP, LONG nDVRPort, DWORD dwUser) { printf("Call DisConnectFunc\n"); printf("lLoginID[0x%x]",lLoginID); if(NULL != pchDVRIP) { printf("pchDVRIP[%s]\n",pchDVRIP); } printf("nDVRPort[%d]\n",nDVRPort); printf("dwUser[%p]\n",dwUser); printf("\n"); }

    摄像头登录

    NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY stInparam; memset(&stInparam, 0, sizeof(stInparam)); stInparam.dwSize = sizeof(stInparam); strncpy(stInparam.szIP, D_Ip, sizeof(stInparam.szIP) - 1); strncpy(stInparam.szPassword, D_Pasdwd, sizeof(stInparam.szPassword) - 1); strncpy(stInparam.szUserName, D_UserName, sizeof(stInparam.szUserName) - 1); stInparam.nPort = D_Port; stInparam.emSpecCap = EM_LOGIN_SPEC_CAP_TCP; tagNET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY stOutparam; LoginHandle = CLIENT_LoginWithHighLevelSecurity(&stInparam, &stOutparam); if (LoginHandle) { QMessageBox::about(NULL,laddr->text(),"连接成功"); } else { printf("login fail\n"); }

    新版的 SDK 建议采用 CLIENT_LoginWithHighLevelSecurity去登陆,旧的CLIENT_LoginEx2已经不建议使用,不安全。

    摄像头监控

    //获取Label句柄 HWND hWnd = (HWND)lplay->winId(); //监视 lHandle = CLIENT_RealPlayEx(LoginHandle,0, hWnd);//实时监视句柄 if (lHandle) { cout << "CLIENT_RealPlayEx success!" << endl; //设置实时监视回调函数 DWORD dwFlag = REALDATA_FLAG_RAW_DATA;//原始数据标志 CLIENT_SetRealDataCallBackEx2(lHandle, &fRealDataCB, NULL,dwFlag); } else { printf("CLIENT_RealPlayEx: failed! Error code: %x.\n",CLIENT_GetLastError()); }

    摄像头监控需要一个窗口句柄。CLIENT_SetRealDataCallBackEx2函数可以得到监控的实时数据。如果不想用句柄的方式就需要通过设置回调的方式去自己接受数据并渲染。

    实时数据回调需要个回调函数fRealDataCB:

    //数据回调 void CALLBACK Widget::fRealDataCB(LLONG lRealHandle, DWORD dwDataType, BYTE *pBuffer, DWORD dwBufSize, LLONG param,LDWORD dwUser) { //printf("receive real data,param:lRealHandle[%p],dwDataType[%d],pBuffer[%p],dwBufSize[%d]\n",lRealHandle,dwDataType,pBuffer,dwBufSize); if(CLIENT_SaveRealData(lHandle,"D:/test.mp4")) { //printf("Save data success\n"); } }

    CLIENT_SaveRealData函数可以将摄像头的数据实时保存到文件。

    摄像头开启客流人数统计

    NET_IN_ATTACH_VIDEOSTAT_SUM InParam={sizeof(NET_IN_ATTACH_VIDEOSTAT_SUM)}; InParam.nChannel=0; InParam.cbVideoStatSum=&VideoStatSumCallback; NET_OUT_ATTACH_VIDEOSTAT_SUM OutParam={0}; OutParam.dwSize=sizeof(OutParam); int nWaitTime=5000; //wait time // 订阅客流量统计 attachpassHnd = CLIENT_AttachVideoStatSummary(LoginHandle,&InParam,&OutParam,nWaitTime); if(attachpassHnd) { cout << "CLIENT_AttachVideoStatSummary sucess!" << endl; } else { cout << "error number:" <<CLIENT_GetLastError() << endl; }

    客流数据需要一个回调函数可以接收到"进入人数","离开人数"等信息:

    //客流数据回调 void CALLBACK Widget::VideoStatSumCallback(LLONG lAttachHandle, NET_VIDEOSTAT_SUMMARY* pBuf, DWORD dwBufLen, LDWORD dwUser) { // 处理回调数据 cout << "\nchannel:" <<pBuf->nChannelID << "\nname:"<< pBuf->szRuleName<< "\nenter:"<< pBuf->stuEnteredSubtotal.nTotal<< "\nleave:"<< pBuf->stuExitedSubtotal.nTotal<< endl; }

    解除客流统计的回调

    CLIENT_DetachVideoStatSummary(attachpassHnd);

    其实大华 SDK 给的文档挺细的,看文档就能知道所有接口的用法。

    本案例Demo下载(csdn):

    https://download.csdn.net/download/u012534831/12567071

    头文件:

    #ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <Windows.h> #include <QHBoxLayout> #include <QVBoxLayout> #include <QLabel> #include <QPushButton> #include <QLineEdit> #include "avglobal.h" #include "dhconfigsdk.h" #include "dhnetsdk.h" #include <QMessageBox> #include <QTime> #include <QFile> #define WIDTH 550 #define HIGH 550 #define IP "192.168.1.108" #define PORT "37777" #define USER "admin" #define PASSWD "abc123456" class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = 0); static void CALLBACK DisConnectFunc(LLONG lLoginID, char *pchDVRIP, LONG nDVRPort, DWORD dwUser); static void CALLBACK fRealDataCB(LLONG lRealHandle, DWORD dwDataType, BYTE *pBuffer, DWORD dwBufSize, LLONG param,LDWORD dwUser); static void CALLBACK HaveReConnect(LLONG lLoginID,char *pchDVRIP,LONG nDVRPort,LDWORD dwUser); static void CALLBACK VideoStatSumCallback(LLONG lAttachHandle, NET_VIDEOSTAT_SUMMARY* pBuf, DWORD dwBufLen, LDWORD dwUser); ~Widget(); private: QLabel *ltitle,*ltitle2,*ltitle3,*ltitle4; QPushButton *pconnect,*pnext,*popenPassengerFlow,*pclosePassengerFlow; QLineEdit *laddr,*lport,*luser,*lpasswd; QLabel *lplay; char D_Ip[32] ={0}; char D_UserName[32] = {0}; char D_Pasdwd[32] = {0}; int D_Port = 37777; int nIndex = 0; private slots: void h_next(); void h_connect(); void h_openPassengerFlow(); void h_closePassengerFlow(); }; #endif // WIDGET_H

    cpp文件:

    #include "widget.h" #include <iostream> #include <stdio.h> #pragma execution_character_set("utf-8") using namespace std; LLONG LoginHandle;//登录句柄 LLONG lHandle;//监视句柄 LLONG attachpassHnd;//订阅客流句柄 #include<QDebug> Widget::Widget(QWidget *parent) : QWidget(parent) { qDebug() << "init"; //设置窗口大小 setMinimumSize(WIDTH, HIGH); //文本名称 ltitle = new QLabel("IP地址 "); ltitle2 = new QLabel("端口号 "); ltitle3 = new QLabel("用户名 "); ltitle4 = new QLabel(" 密码 "); //网络地址 连接 laddr = new QLineEdit(IP); lport = new QLineEdit(PORT); luser = new QLineEdit(USER); lpasswd = new QLineEdit(PASSWD); //按钮 pconnect = new QPushButton("连接"); pnext = new QPushButton("显示"); popenPassengerFlow = new QPushButton("开启客流数据采集"); pclosePassengerFlow= new QPushButton("关闭客流数据采集"); //显示 lplay = new QLabel; //控件组合 QHBoxLayout *hbox1 = new QHBoxLayout; hbox1->addStretch(); hbox1->addWidget(ltitle); hbox1->addWidget(laddr); hbox1->addStretch(); hbox1->addWidget(ltitle2); hbox1->addWidget(lport); hbox1->addStretch(); QHBoxLayout *hbox2 = new QHBoxLayout; hbox2->addStretch(); hbox2->addWidget(ltitle3); hbox2->addWidget(luser); hbox2->addStretch(); hbox2->addWidget(ltitle4); hbox2->addWidget(lpasswd); hbox2->addStretch(); QHBoxLayout *hbox3 = new QHBoxLayout; hbox3->addWidget(pconnect); hbox3->addWidget(pnext); QHBoxLayout *hbox4 = new QHBoxLayout; hbox4->addWidget(popenPassengerFlow); hbox4->addWidget(pclosePassengerFlow); QVBoxLayout *vbox1 = new QVBoxLayout; vbox1->addLayout(hbox1); vbox1->addLayout(hbox2); vbox1->addLayout(hbox3); vbox1->addLayout(hbox4); vbox1->addWidget(lplay); setLayout(vbox1); //槽函数 connect(pnext, SIGNAL(clicked(bool)), this, SLOT(h_next())); connect(pconnect, SIGNAL(clicked(bool)), this, SLOT(h_connect())); connect(popenPassengerFlow, SIGNAL(clicked(bool)), this, SLOT(h_openPassengerFlow())); connect(pclosePassengerFlow, SIGNAL(clicked(bool)), this, SLOT(h_closePassengerFlow())); } Widget::~Widget() { cout<<"CLOSED!"<<endl; //停止实时监视 CLIENT_StopRealPlayEx(lHandle); //登出设备 CLIENT_Logout(LoginHandle); //清理SDK资源 CLIENT_Cleanup(); } void Widget::h_connect() { //获取界面登录信息 strcpy(D_Ip,laddr->text().toLatin1().data()); strcpy(D_UserName,luser->text().toLatin1().data()); strcpy(D_Pasdwd,lpasswd->text().toLatin1().data()); D_Port = lport->text().toInt(); //SDK初始化 if(CLIENT_Init((fDisConnect)DisConnectFunc, (LDWORD)0)) { cout<<"SDK INIT OK!"<<endl; } else { cout<<"SDK INIT FAIL!"<<endl; } //获取SDK版本信息 DWORD dwNetSdkVersion = CLIENT_GetSDKVersion(); printf("NetSDK version is [%d]\n",dwNetSdkVersion); //设置断线重连回调接口,设置过断线重连成功回调函数后,当设备出现断线情况,SDK内部会自动进行重连操作 CLIENT_SetAutoReconnect(&HaveReConnect,0); //设置登录超时时间和尝试次数 int nWaitTime = 5000; //登录请求响应超时时间设置为5s int nTryTimes = 3; //登录时尝试建立连接3次 CLIENT_SetConnectTime(nWaitTime,nTryTimes); //设置更多网络参数,NET_PARAM的nWaittime,nConnectTryNum成员与CLIENT_SetConnectTime 接口设置的登录设备超时时间和尝试次数的意义相同 NET_PARAM stuNetparm ={0}; stuNetparm.nConnectTime = 3000;//登录时尝试建立连接的超时时间 CLIENT_SetNetworkParam(&stuNetparm); // 登录 NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY stInparam; memset(&stInparam, 0, sizeof(stInparam)); stInparam.dwSize = sizeof(stInparam); strncpy(stInparam.szIP, D_Ip, sizeof(stInparam.szIP) - 1); strncpy(stInparam.szPassword, D_Pasdwd, sizeof(stInparam.szPassword) - 1); strncpy(stInparam.szUserName, D_UserName, sizeof(stInparam.szUserName) - 1); stInparam.nPort = D_Port; stInparam.emSpecCap = EM_LOGIN_SPEC_CAP_TCP; tagNET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY stOutparam; LoginHandle = CLIENT_LoginWithHighLevelSecurity(&stInparam, &stOutparam); if (LoginHandle) { QMessageBox::about(NULL,laddr->text(),"连接成功"); } else { printf("login fail\n"); } } void Widget::h_next() { if(FALSE == LoginHandle) { QMessageBox::about(NULL,laddr->text(),"连接失败"); return; } //获取Label句柄 HWND hWnd = (HWND)lplay->winId(); //监视 lHandle = CLIENT_RealPlayEx(LoginHandle,0, hWnd);//实时监视句柄 if (lHandle) { cout << "CLIENT_RealPlayEx success!" << endl; //设置实时监视回调函数 DWORD dwFlag = REALDATA_FLAG_RAW_DATA;//原始数据标志 CLIENT_SetRealDataCallBackEx2(lHandle, &fRealDataCB, NULL,dwFlag); } else { printf("CLIENT_RealPlayEx: failed! Error code: %x.\n",CLIENT_GetLastError()); } } void Widget::h_openPassengerFlow() { if(FALSE == LoginHandle) { QMessageBox::about(NULL,laddr->text(),"未连接登录"); return; } NET_IN_ATTACH_VIDEOSTAT_SUM InParam={sizeof(NET_IN_ATTACH_VIDEOSTAT_SUM)}; InParam.nChannel=0; InParam.cbVideoStatSum=&VideoStatSumCallback; NET_OUT_ATTACH_VIDEOSTAT_SUM OutParam={0}; OutParam.dwSize=sizeof(OutParam); int nWaitTime=5000; //wait time // 订阅客流量统计 attachpassHnd = CLIENT_AttachVideoStatSummary(LoginHandle,&InParam,&OutParam,nWaitTime); if(attachpassHnd) { cout << "CLIENT_AttachVideoStatSummary sucess!" << endl; } else { cout << "error number:" <<CLIENT_GetLastError() << endl; } } void Widget::h_closePassengerFlow() { if(FALSE == LoginHandle) { QMessageBox::about(NULL,laddr->text(),"未连接登录"); return; } if(FALSE == attachpassHnd) { QMessageBox::about(NULL,laddr->text(),"未订阅客流统计"); return; } CLIENT_DetachVideoStatSummary(attachpassHnd); } //客流数据回调 void CALLBACK Widget::VideoStatSumCallback(LLONG lAttachHandle, NET_VIDEOSTAT_SUMMARY* pBuf, DWORD dwBufLen, LDWORD dwUser) { // 处理回调数据 cout << "\nchannel:" <<pBuf->nChannelID << "\nname:"<< pBuf->szRuleName<< "\nenter:"<< pBuf->stuEnteredSubtotal.nTotal<< "\nleave:"<< pBuf->stuExitedSubtotal.nTotal<< endl; } //断线回调 void CALLBACK Widget::DisConnectFunc(LLONG lLoginID, char *pchDVRIP, LONG nDVRPort, DWORD dwUser) { printf("Call DisConnectFunc\n"); printf("lLoginID[0x%x]",lLoginID); if(NULL != pchDVRIP) { printf("pchDVRIP[%s]\n",pchDVRIP); } printf("nDVRPort[%d]\n",nDVRPort); printf("dwUser[%p]\n",dwUser); printf("\n"); } //数据回调 void CALLBACK Widget::fRealDataCB(LLONG lRealHandle, DWORD dwDataType, BYTE *pBuffer, DWORD dwBufSize, LLONG param,LDWORD dwUser) { //printf("receive real data,param:lRealHandle[%p],dwDataType[%d],pBuffer[%p],dwBufSize[%d]\n",lRealHandle,dwDataType,pBuffer,dwBufSize); if(CLIENT_SaveRealData(lHandle,"D:/test.mp4")) { //printf("Save data success\n"); } } //重连回调 void CALLBACK Widget::HaveReConnect(LLONG lLoginID,char *pchDVRIP,LONG nDVRPort,LDWORD dwUser) { printf("Call HaveReConnect\n"); printf("lLoginID[0x%x]",lLoginID); if(NULL != pchDVRIP) { printf("pchDVRIP[%s]\n",pchDVRIP); } printf("nDVRPort[%d]\n",nDVRPort); printf("dwUser[%p]\n",dwUser); printf("\n"); }

    如有帮助,请多多点赞支持。

    Processed: 0.011, SQL: 9