Qt下集成大华网络相机SDK示例开发

发布于:2025-03-23 ⋅ 阅读:(32) ⋅ 点赞:(0)


前言

近期在Qt环境下进行大华网络相机的使用,发现官网下载的SDK中提供的示例没有Qt的demo,通过学习其提供的MFC示例代码,我在这里也实现了一个比较简单的Qt下调用大华网络相机的示例程序,并将相关代码展现出来以便大家学习,如有错误之处,欢迎大家批评指正。

项目效果
请添加图片描述


提示:以下是本篇文章正文内容,下面案例可供参考

一、下载并集成大华网络相机SDK

到大华官网进行下载:大华设备网络SDK,也可以通过文末我的百度网盘链接下载本示例使用到的SDK(建议直接官网进行下载,有详细的示例文档及函数接口说明)

在官网下根据项目需求选择对应的SDK,下面是本示例使用到的:
在这里插入图片描述

在集成该SDK时,我是把需要用到的h和lib文件打包在一个文件夹内,然后放在项目pro文件的同级目录下,然后在pro文件中添加下列代码:(也可以直接在Qt中通过添加库的方式进行集成)

#SDK
INCLUDEPATH += $$PWD/SDK/Includes
DEPENDPATH += $$PWD/SDK/Includes
LIBS += -L$$PWD/SDK/Lib/ -ldhnetsdk

SDK文件夹内容如图(dll文件夹中存放程序运行时需要的dll,运行时需要放在exe同级目录下)
在这里插入图片描述

二、示例实现功能

在我的示例项目代码中有详细的注释,这里就不对各功能一一介绍了:

1.绑定窗口句柄实时显示相机数据:

//开始
void Widget::on_pb_start_clicked()
{
    if(0 != m_lRealPlayHandle)
    {
        CLIENT_StopRealPlay(m_lRealPlayHandle);
        m_lRealPlayHandle = 0;

        ui->pb_start->setText("开始");
    }
    else
    {
        int nChannel = 0;
        HWND hWnd = reinterpret_cast<HWND>(ui->lb_show->winId());
        m_lRealPlayHandle = CLIENT_StartRealPlay(m_lLoginHandle, nChannel, hWnd, DH_RType_Realplay, NULL, NULL, NULL);
        if (0 == m_lRealPlayHandle)
        {
            QMessageBox::information(this,"提示","开始失败!");
            return;
        }
        ui->pb_start->setText("停止");
        CLIENT_RenderPrivateData(m_lRealPlayHandle, TRUE);
    }
}

2.开启智能事件订阅,绑定事件回调:

//订阅
void Widget::on_pb_event_clicked()
{
    if (0 != m_lRealLoadHandle)
        {
            CLIENT_StopLoadPic(m_lRealLoadHandle);
            m_lRealLoadHandle = 0;
            ui->pb_event->setText("订阅");
        }
        else
        {
            int nChannel = 0;
            m_lRealLoadHandle = CLIENT_RealLoadPictureEx(m_lLoginHandle, nChannel, EVENT_IVS_ALL, TRUE, EventCallback, (LDWORD)this, NULL);
            if (m_lRealLoadHandle == 0)
            {
                QMessageBox::information(this,"提示","订阅失败!");
                return;
            }
            ui->pb_event->setText("停止订阅");
        }
}

//事件回调
int CALLBACK Widget::EventCallback(LLONG lAnalyzerHandle, DWORD dwAlarmType, void* pAlarmInfo, BYTE *pBuffer, DWORD dwBufSize, LDWORD dwUser, int nSequence, void *reserved)
{
    if(0 == dwUser)
    {
        return -1;
    }

    //绊线入侵事件
    if(dwAlarmType == EVENT_IVS_CROSSLINEDETECTION)   //EVENT_IVS_HUMANTRAIT
    {
        //检查是否有有效的图像数据
        if (pBuffer == NULL || dwBufSize == 0)
        {
            LOGDEBUG<<"事件回调图像数据无效";
            return -1;
        }

        //保存图像
        QPointer<Widget> camera = reinterpret_cast<Widget*>(dwUser);
        QMetaObject::invokeMethod(camera, [=]()
        {
            //这里SaveImage中有直接操作ui控件,所以需要使用QMetaObject::invokeMethod
            camera->SaveImage(pBuffer,dwBufSize);
        });
    }
    return 0;
}

3.主动抓图,触发抓图回调并保存图像:

//抓图
void Widget::on_pb_get_clicked()
{
    if (0 != m_lLoginHandle)
    {
        //主动抓图
        SNAP_PARAMS snapparams = {0};
        snapparams.Channel = 0;
        snapparams.mode = 0;
        snapparams.CmdSerial = 0;
        BOOL flag = CLIENT_SnapPicture(m_lLoginHandle, snapparams);
        if (!flag)
        {
            QMessageBox::information(this,"提示","抓图失败!");
        }
        else
        {
            ui->pte_text->appendPlainText("开始抓图");
        }
    }
}

//抓图回调
void CALLBACK Widget::CaptureCallback(LLONG ILoginID, BYTE *pBuf, UINT RevLen, UINT EncodeType, DWORD CmdSerial, LDWORD dwUser)
{
    //跨线程调用,相机回调函数是有另开子线程的
    QPointer<Widget> camera = reinterpret_cast<Widget*>(dwUser);
    QMetaObject::invokeMethod(camera, [=]()
    {
        //多个相机就需要
        //if(ILoginID == camera->m_lLoginHandle)
        {
            camera->OnOnePicture(ILoginID,pBuf,RevLen,EncodeType,CmdSerial);
        }
    });
}

//抓图
void Widget::OnOnePicture(LLONG ILoginID, BYTE *pBuf, UINT RevLen, UINT EncodeType, UINT CmdSerial)
{
    //检查输入合法性
    if(!pBuf || RevLen == 0)
    {
        LOGDEBUG<<"抓图图像数据无效";
        return;
    }

    //保存图像
    SaveImage(pBuf,RevLen);
}

//保存图像
bool Widget::SaveImage(BYTE *pBuffer, DWORD dwBufSize)
{
    //定义输出文件名
    static int num = 0;
    num++;
    char outputFileName[256];
    snprintf(outputFileName, sizeof(outputFileName), "output_image_%d.jpg", num);

    //打开文件以写入二进制数据
    FILE* file = fopen(outputFileName, "wb");
    if (file == NULL)
    {
        LOGDEBUG<<"图像保存失败!";
        return false;
    }

    //写入图像数据到文件
    fwrite(pBuffer, 1, dwBufSize, file);

    //关闭文件
    fclose(file);

    LOGDEBUG<<"图像保存成功!";
    ui->pte_text->appendPlainText("图像保存成功!");
    return true;
}

4.鼠标事件过滤,进行云台控制

//事件过滤器
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
    if(watched ==ui->lb_show)
    {
        QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
        if (event->type() == QEvent::MouseButtonPress)
        {
            //鼠标按下,记录起点
            m_startPos = mouseEvent->pos();
            m_currentPos = m_startPos;
            m_drawing = true;
            return true;
        }
        else if (event->type() == QEvent::MouseMove && m_drawing)
        {
            //鼠标移动,更新终点并绘制临时矩形
            m_currentPos = mouseEvent->pos();
            return true;
        }
        else if (event->type() == QEvent::MouseButtonRelease && m_drawing)
        {
            //鼠标释放,绘制最终矩形
            m_drawing = false;
            m_currentPos = mouseEvent->pos();

            //坐标转换
            QRect winRect = ui->lb_show->rect();
            double xScale =  winRect.width() / 2560.0;
            double yScale =  winRect.height() / 1440.0;
            m_startPos = QPoint(m_startPos.x()/xScale,m_startPos.y()/yScale);
            m_currentPos = QPoint(m_currentPos.x()/xScale,m_currentPos.y()/yScale);
            UpDateShow(m_startPos,m_currentPos);
            return true;
        }
    }
    return QWidget::eventFilter(watched,event);
}

5.相机断线与重连回调:

//设备断连回调
void CALLBACK Widget::DisConnect(LLONG lLoginID, char *pchDVRIP, LONG nDVRPort, LDWORD dwUser)
{
    if(0 != dwUser)
    {
        QPointer<Widget> camera = reinterpret_cast<Widget*>(dwUser);
        camera->SetConnect(0);
    }
}

//设备重连回调
void CALLBACK Widget::ReConnect(LLONG lLoginID, char *pchDVRIP, LONG nDVRPort, LDWORD dwUser)
{
    if(0 != dwUser)
    {
        QPointer<Widget> camera = reinterpret_cast<Widget*>(dwUser);
        camera->SetConnect(1);
    }
}

、、、、、、

三、示例完整代码

1.DahuaDemo.pro

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

DEFINES += QT_DEPRECATED_WARNINGS

SOURCES += \
    main.cpp \
    widget.cpp

HEADERS += \
    widget.h \

FORMS += \
    widget.ui

qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

#SDK
INCLUDEPATH += $$PWD/SDK/Includes
DEPENDPATH += $$PWD/SDK/Includes
LIBS += -L$$PWD/SDK/Lib/ -ldhnetsdk

2.widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QObject>
#include <QMessageBox>
#include <QPen>
#include <QPainter>
#include <QMouseEvent>
#include <QLabel>
#include <QRect>
#include <QTime>
#include <QTimer>
#include <QPointer>
#include <QDebug>

#include "dhnetsdk.h"

#define LOGDEBUG qDebug()<<QTime::currentTime().toString("[hh:mm:ss:zzz]")

using namespace std;

struct HUMAN_TRAIT_EVENT_INFO
{
    DEV_EVENT_HUMANTRAIT_INFO stuEvent;
    BYTE* pBuf;
    int nBufSize;
};

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    void InitWidget();
    void InitNetSDK();

    void SetConnect(int type);
    bool SaveImage(BYTE *pBuffer, DWORD dwBufSize);
    void UpDateShow(const QPoint &start, const QPoint &end);

    void PtzExtControl(DWORD dwCommand, DWORD dwParam = 0);
    void OnOnePicture(LLONG ILoginID, BYTE *pBuf, UINT RevLen, UINT EncodeType, UINT CmdSerial);

protected:
    bool eventFilter(QObject *watched, QEvent *event);

private:
    static void CALLBACK DisConnect(LLONG lLoginID, char *pchDVRIP, LONG nDVRPort, LDWORD dwUser);
    static void CALLBACK ReConnect(LLONG lLoginID, char *pchDVRIP, LONG nDVRPort, LDWORD dwUser);
    static void CALLBACK CaptureCallback(LLONG ILoginID, BYTE *pBuf, UINT RevLen, UINT EncodeType, DWORD CmdSerial, LDWORD dwUser);
    static int CALLBACK EventCallback(LLONG lAnalyzerHandle, DWORD dwAlarmType, void* pAlarmInfo, BYTE *pBuffer, DWORD dwBufSize, LDWORD dwUser, int nSequence, void *reserved);

private slots:
    void on_pb_login_clicked();
    void on_pb_start_clicked();
    void on_pb_event_clicked();
    void on_pb_get_clicked();

private:
    Ui::Widget *ui;

    LLONG m_lLoginHandle;      //登录句柄
    LLONG m_lRealPlayHandle;   //播放句柄
    LLONG m_lRealLoadHandle;   //订阅句柄

    int m_posX;   //水平坐标
    int m_posY;   //垂直坐标
    int m_posZoom;    //变倍
    bool m_drawing;   //绘制标志
    QPoint m_startPos;     //鼠标起点
    QPoint m_currentPos;   //鼠标当前点


};
#endif // WIDGET_H

3.widget.cpp

#include "widget.h"
#include "ui_widget.h"

#pragma execution_character_set("utf-8")

//LLONG m_lHandle;

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    InitWidget();
}

Widget::~Widget()
{
    delete ui;

    if(0 != m_lLoginHandle)
    {
        on_pb_login_clicked();
    }
    CLIENT_Cleanup();
}

//初始化界面
void Widget::InitWidget()
{
    m_lLoginHandle = 0;
    m_lRealPlayHandle = 0;
    m_lRealLoadHandle = 0;

    ui->le_ip->setText("192.168.1.108");
    ui->le_port->setText("37777");
    ui->le_user->setText("admin");
    ui->le_password->setText("12345678");
    ui->lb_show->installEventFilter(this);

    //初始化相机
    InitNetSDK();

}

//初始化相机
void Widget::InitNetSDK()
{
    //初始化
    BOOL ret = CLIENT_Init(DisConnect, (LDWORD)this);
    if (ret)
    {
        LOG_SET_PRINT_INFO  stLogPrintInfo = {sizeof(stLogPrintInfo)};
        CLIENT_LogOpen(&stLogPrintInfo);

        //初始化成功后设置网络参数
        //目前仅单独设置获取设备信息时间(部分设备因性能问题,没法在默认时间内完成,其他参数暂时保持默认)
        NET_PARAM stuNetParam = {0};
        stuNetParam.nGetDevInfoTime = 3000;
        stuNetParam.nPicBufSize = 10*1024*1024;
        CLIENT_SetNetworkParam(&stuNetParam);

        //设置回调
        CLIENT_SetSnapRevCallBack(CaptureCallback,(LDWORD)this);
        CLIENT_SetAutoReconnect(ReConnect, (LDWORD)this);
    }
    else
    {
        QMessageBox::information(this,"提示","初始化SDK失败!");
    }
}

//设置连接
void Widget::SetConnect(int type)
{
    if(type == 0)
    {
        LOGDEBUG<<"相机断连";
    }
    else
    {
        LOGDEBUG<<"相机重连";
    }
}

//保存图像
bool Widget::SaveImage(BYTE *pBuffer, DWORD dwBufSize)
{
    //定义输出文件名
    static int num = 0;
    num++;
    char outputFileName[256];
    snprintf(outputFileName, sizeof(outputFileName), "output_image_%d.jpg", num);

    //打开文件以写入二进制数据
    FILE* file = fopen(outputFileName, "wb");
    if (file == NULL)
    {
        LOGDEBUG<<"图像保存失败!";
        return false;
    }

    //写入图像数据到文件
    fwrite(pBuffer, 1, dwBufSize, file);

    //关闭文件
    fclose(file);

    LOGDEBUG<<"图像保存成功!";
    ui->pte_text->appendPlainText("图像保存成功!");
    return true;
}

//更新界面显示
void Widget::UpDateShow(const QPoint &start, const QPoint &end)
{
    QRect winRect = ui->lb_show->rect();   //窗口矩形区域

    //LOGDEBUG<<"start:"<<start<<"   end:"<<end;
    double xScale =  winRect.width() / 2560.0;
    double yScale =  winRect.height() / 1440.0;
    QPoint pointStart = QPoint(start.x()*xScale,start.y()*yScale);   //起始点
    QPoint pointEnd = QPoint(end.x()*xScale,end.y()*yScale);   //结束点
    //LOGDEBUG<<"pointStart:"<<pointStart<<"   pointEnd:"<<pointEnd;

    QPoint origin;
    QPoint sendPoint;

    //计算窗口中心点(Qt的坐标系以左上角为原点)
    origin.setX( (winRect.left() + winRect.right()) / 2 );
    origin.setY( (winRect.top() + winRect.bottom()) / 2 );

    //计算两点中点坐标
    int dx = (pointStart.x() + pointEnd.x()) / 2;
    int dy = (pointStart.y() + pointEnd.y()) / 2;

    //获取窗口尺寸(Qt推荐使用width()/height()方法)
    int width  = winRect.width();
    int height = winRect.height();

    //坐标映射:将中点坐标转换为标准化的设备坐标
    //注意:Qt的Y轴方向向下,根据具体需求可能需要符号处理
    sendPoint.setX( (dx - origin.x()) * 8192 * 2 / width );
    sendPoint.setY( (dy - origin.y()) * 8192 * 2 / height ); // 反转Y轴方向

    //计算拖动区域尺寸(允许负值)
    int width2  = pointEnd.x() - pointStart.x();
    int height2 = pointEnd.y() - pointStart.y();
    int multiple = 0;

    //计算面积比例(带方向)
    if (height2 != 0 && width2 != 0)
    {
        if (pointEnd.y() >= pointStart.y())
        {
            multiple = (width * height) / (width2 * height2);
        }
        else
        {
            multiple = -(width * height) / (width2 * height2);
        }
    }
    m_posX = sendPoint.x();
    m_posY = sendPoint.y();
    m_posZoom = multiple;
    //qDebug()<<"m_posX:"<<m_posX<<"   m_posY:"<<m_posY<<"   m_posZoom:"<<m_posZoom;
    PtzExtControl(DH_EXTPTZ_FASTGOTO);
}

//云台控制
void Widget::PtzExtControl(DWORD dwCommand, DWORD dwParam)
{
    if (0 == m_lLoginHandle)
    {
        return;
    }

    long param1=0,param2=0,param3 = 0;
    char param4[256]={0};
    char *pchPresetName = NULL;
    switch(dwCommand) {
        case DH_PTZ_POINT_MOVE_CONTROL:
                //Go to preset
                param1=0;
                param2=1;
                param3=0;
                break;
        case DH_PTZ_POINT_SET_CONTROL:
                //Add preset
                param1=0;
                param2=1;
                param3=0;
                break;
        case DH_EXTPTZ_FASTGOTO:   //快速定位
        case DH_EXTPTZ_EXACTGOTO:
            //3D intelligent position
            param1=m_posX;
            param2=m_posY;
            param3=m_posZoom;
            break;
        case DH_EXTPTZ_RESETZERO:
            param1=0;
            param2=0;
            param3=0;
            break;
        default:
            break;
    }
    BOOL bRet=CLIENT_DHPTZControlEx2(m_lLoginHandle,0,dwCommand,param1,param2,param3,FALSE,(void*)param4);
    if(bRet)
    {
        LOGDEBUG<<"移动成功!";
    }
    else
    {
        LOGDEBUG<<"移动失败!";
    }
}

//抓图
void Widget::OnOnePicture(LLONG ILoginID, BYTE *pBuf, UINT RevLen, UINT EncodeType, UINT CmdSerial)
{
    //检查输入合法性
    if(!pBuf || RevLen == 0)
    {
        LOGDEBUG<<"抓图图像数据无效";
        return;
    }

    //保存图像
    SaveImage(pBuf,RevLen);
}

//事件过滤器
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
    if(watched ==ui->lb_show)
    {
        QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
        if (event->type() == QEvent::MouseButtonPress)
        {
            //鼠标按下,记录起点
            m_startPos = mouseEvent->pos();
            m_currentPos = m_startPos;
            m_drawing = true;
            return true;
        }
        else if (event->type() == QEvent::MouseMove && m_drawing)
        {
            //鼠标移动,更新终点并绘制临时矩形
            m_currentPos = mouseEvent->pos();
            return true;
        }
        else if (event->type() == QEvent::MouseButtonRelease && m_drawing)
        {
            //鼠标释放,绘制最终矩形
            m_drawing = false;
            m_currentPos = mouseEvent->pos();

            //坐标转换
            QRect winRect = ui->lb_show->rect();
            double xScale =  winRect.width() / 2560.0;
            double yScale =  winRect.height() / 1440.0;
            m_startPos = QPoint(m_startPos.x()/xScale,m_startPos.y()/yScale);
            m_currentPos = QPoint(m_currentPos.x()/xScale,m_currentPos.y()/yScale);
            UpDateShow(m_startPos,m_currentPos);
            return true;
        }
    }
    return QWidget::eventFilter(watched,event);
}

//设备断连回调
void CALLBACK Widget::DisConnect(LLONG lLoginID, char *pchDVRIP, LONG nDVRPort, LDWORD dwUser)
{
    if(0 != dwUser)
    {
        QPointer<Widget> camera = reinterpret_cast<Widget*>(dwUser);
        camera->SetConnect(0);
    }
}

//设备重连回调
void CALLBACK Widget::ReConnect(LLONG lLoginID, char *pchDVRIP, LONG nDVRPort, LDWORD dwUser)
{
    if(0 != dwUser)
    {
        QPointer<Widget> camera = reinterpret_cast<Widget*>(dwUser);
        camera->SetConnect(1);
    }
}

//抓图回调
void CALLBACK Widget::CaptureCallback(LLONG ILoginID, BYTE *pBuf, UINT RevLen, UINT EncodeType, DWORD CmdSerial, LDWORD dwUser)
{
    //跨线程调用,相机回调函数是有另开子线程的
    QPointer<Widget> camera = reinterpret_cast<Widget*>(dwUser);
    QMetaObject::invokeMethod(camera, [=]()
    {
        //多个相机就需要
        //if(ILoginID == camera->m_lLoginHandle)
        {
            camera->OnOnePicture(ILoginID,pBuf,RevLen,EncodeType,CmdSerial);
        }
    });
}

//事件回调
int CALLBACK Widget::EventCallback(LLONG lAnalyzerHandle, DWORD dwAlarmType, void* pAlarmInfo, BYTE *pBuffer, DWORD dwBufSize, LDWORD dwUser, int nSequence, void *reserved)
{
    if(0 == dwUser)
    {
        return -1;
    }

    //绊线入侵事件
    if(dwAlarmType == EVENT_IVS_CROSSLINEDETECTION)   //EVENT_IVS_HUMANTRAIT
    {
        //检查是否有有效的图像数据
        if (pBuffer == NULL || dwBufSize == 0)
        {
            LOGDEBUG<<"事件回调图像数据无效";
            return -1;
        }

        //保存图像
        QPointer<Widget> camera = reinterpret_cast<Widget*>(dwUser);
        QMetaObject::invokeMethod(camera, [=]()
        {
            //这里SaveImage中有直接操作ui控件,所以需要使用QMetaObject::invokeMethod
            camera->SaveImage(pBuffer,dwBufSize);
        });
    }
    return 0;
}

//登录
void Widget::on_pb_login_clicked()
{
    if (0 != m_lLoginHandle )
    {
        if (0 != m_lRealPlayHandle)
        {
            on_pb_start_clicked();
        }
        if (0 != m_lRealLoadHandle)
        {

        }

        CLIENT_Logout(m_lLoginHandle);
        m_lLoginHandle = 0;

        ui->pb_login->setText("登录");
    }
    else
    {
        NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY stInparam;
        memset(&stInparam, 0, sizeof(stInparam));
        stInparam.dwSize = sizeof(stInparam);
        strncpy(stInparam.szIP, ui->le_ip->text().toLocal8Bit(), sizeof(stInparam.szIP) - 1);
        strncpy(stInparam.szPassword, ui->le_password->text().toLocal8Bit(), sizeof(stInparam.szPassword) - 1);
        strncpy(stInparam.szUserName, ui->le_user->text().toLocal8Bit(), sizeof(stInparam.szUserName) - 1);
        stInparam.nPort = ui->le_port->text().toInt();
        stInparam.emSpecCap = EM_LOGIN_SPEC_CAP_TCP;

        NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY stOutparam;
        memset(&stOutparam, 0, sizeof(stOutparam));
        stOutparam.dwSize = sizeof(stOutparam);
        m_lLoginHandle = CLIENT_LoginWithHighLevelSecurity(&stInparam, &stOutparam);

        if (0 != m_lLoginHandle)
        {
            ui->pb_login->setText("登出");
        }
        else
        {
            QMessageBox::information(this,"提示","登录失败!");
            m_lLoginHandle = 0;
        }
    }
}

//开始
void Widget::on_pb_start_clicked()
{
    if(0 != m_lRealPlayHandle)
    {
        CLIENT_StopRealPlay(m_lRealPlayHandle);
        m_lRealPlayHandle = 0;

        ui->pb_start->setText("开始");
    }
    else
    {
        int nChannel = 0;
        HWND hWnd = reinterpret_cast<HWND>(ui->lb_show->winId());
        m_lRealPlayHandle = CLIENT_StartRealPlay(m_lLoginHandle, nChannel, hWnd, DH_RType_Realplay, NULL, NULL, NULL);
        if (0 == m_lRealPlayHandle)
        {
            QMessageBox::information(this,"提示","开始失败!");
            return;
        }
        ui->pb_start->setText("停止");
        CLIENT_RenderPrivateData(m_lRealPlayHandle, TRUE);
    }
}

//订阅
void Widget::on_pb_event_clicked()
{
    if (0 != m_lRealLoadHandle)
        {
            CLIENT_StopLoadPic(m_lRealLoadHandle);
            m_lRealLoadHandle = 0;
            ui->pb_event->setText("订阅");
        }
        else
        {
            int nChannel = 0;
            m_lRealLoadHandle = CLIENT_RealLoadPictureEx(m_lLoginHandle, nChannel, EVENT_IVS_ALL, TRUE, EventCallback, (LDWORD)this, NULL);
            if (m_lRealLoadHandle == 0)
            {
                QMessageBox::information(this,"提示","订阅失败!");
                return;
            }
            ui->pb_event->setText("停止订阅");
        }
}

//抓图
void Widget::on_pb_get_clicked()
{
    if (0 != m_lLoginHandle)
    {
        //主动抓图
        SNAP_PARAMS snapparams = {0};
        snapparams.Channel = 0;
        snapparams.mode = 0;
        snapparams.CmdSerial = 0;
        BOOL flag = CLIENT_SnapPicture(m_lLoginHandle, snapparams);
        if (!flag)
        {
            QMessageBox::information(this,"提示","抓图失败!");
        }
        else
        {
            ui->pte_text->appendPlainText("开始抓图");
        }
    }
}

4.widget.ui
在这里插入图片描述

四、下载链接

我这里将使用到的SDK打包在百度网盘,链接:https://pan.baidu.com/s/1RvS1qxdlkw6leKyGMGrOzQ?pwd=xxcj
提取码: xxcj


总结

这个示例实现了Qt下调用大华网络相机SDK进行实时显示,相较于大华提供的demo也是精简了部分功能,详细的可以运行官网提供的demo进行学习。在本文中有写到对智能事件的订阅回调,这个是需要通过浏览器对网络相机进行配置的,可以查看使用说明书来进行配置哦。


hello:
共同学习,共同进步,如果还有相关问题,可在评论区留言进行讨论。

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