基于大华SDK的二次开发,用于网络摄像头图像的实时显示和捕获(附源码)

目录

1. 文章背景

2. 主要模块

2.1 初始化SDK     

2.2 登录账号

2.3 捕获图片

2.4 实时显示

2.5 断开时释放

2.6 回调函数

3. 源代码

3.1 头文件

3.2 源文件



1. 文章背景

        项目中需要使用大华的网络摄像头,之前为了图方便,我是通过opencv打开rtsp地址,从而显示和存图,但由于客户后期更换了摄像头,且希望采图效率更高,预估rtsp难以达到,所以考虑从大华官方SDK下手,就有了这篇文章。

2. 主要模块

        其实官方的例程已经写得很详细了,不过官方的Demo是用MFC写的,考虑到一些朋友对MFC不是很熟(主要是指我自己 0-0),我就用qt c++写了这部分功能,因为基于QT,所以我的很多代码习惯是qt的,比如实时图像显示的窗体句柄,我是直接取的Qt上的一个QLbel的句柄。

2.1 初始化SDK     

        初始SDK:CLIENT_Init,就一个接口,没啥好说的。

// 初始化 SDK
    g_bNetSDKInitFlag = CLIENT_Init((fDisConnect)DisConnectFunc, 0);
    QString logInfo = QSC("SDK初始化%1。").arg(g_bSnapPictureFlag ? QSC("成功") : QSC("失败"));
    qDebug() << logInfo;

2.2 登录账号

        按摄像头信息登录:CLIENT_LoginWithHighLevelSecurity,这里需要注意的就是把ip,port,用户,密码这些信息按照固定格式存进输入参数结构里,再调相应的接口就好了。

//获取登录信息
    strcpy(D_Ip, ip.toLatin1().data());
    strcpy(D_UserName, name.toLatin1().data());
    strcpy(D_Pasdwd, password.toLatin1().data());
    D_Port = port;

    strncpy(stInparam.szIP, D_Ip, sizeof(stInparam.szIP) - 1);
    strncpy(stInparam.szUserName, D_UserName, sizeof(stInparam.szUserName) - 1);
    strncpy(stInparam.szPassword, D_Pasdwd, sizeof(stInparam.szPassword) - 1);
    stInparam.nPort = D_Port;
    stInparam.emSpecCap = EM_LOGIN_SPEC_CAP_TCP;
    
// 登录设备
    tagNET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY stOutparam;
    LoginHandle = CLIENT_LoginWithHighLevelSecurity(&stInparam, &stOutparam);
    QString logInfo = QSC("设备登录%1:%2 %3。").arg(ip).arg(D_Port).arg(LoginHandle? QSC("成功") : QSC("失败,错误码[%1]").arg(QString::number(CLIENT_GetLastError(), 16)));
    qDebug() << logInfo;

2.3 捕获图片

        捕获图片要做两个动作:

1. 首先是设置回调函数:CLIENT_SetSnapRevCallBack(回调函数名, NULL); 回调函数的内容在后面我会贴出来。

2. 然后在你想抓图的时候调抓图接口:CLIENT_SnapPictureEx(登录句柄, &stuSnapParams);

// 设置抓图回调函数
    CLIENT_SetSnapRevCallBack(SnapRev, NULL);
    //事例中默认通道 ID 为 0、抓图模式为抓一幅图,用户可根据实际情况自行选择
    int nChannelId = 0;
    int nSnapType = 0;// 抓图模式;-1:表示停止抓图, 0:表示请求一帧, 1:表示定时发送请求, 2:表示连续请求
    // 发送抓图命令给前端设备
    SNAP_PARAMS stuSnapParams;
    stuSnapParams.Channel = nChannelId;
    stuSnapParams.mode = nSnapType;
    stuSnapParams.CmdSerial = 0;//++g_nCmdSerial; // 请求序列号,有效值范围 0~65535,超过范围会被截断为 unsigned short
    g_bSnapPictureFlag = CLIENT_SnapPictureEx(LoginHandle, &stuSnapParams);
    QString logInfo = QSC("SDK抓图%1。").arg(g_bSnapPictureFlag? QSC("成功") : QSC("失败,错误码[%1]").arg(QString::number(CLIENT_GetLastError(), 16)));
    qDebug() << logInfo;

2.4 实时显示

        实时显示有两种方式:一是直接在某个窗体句柄下显示;二是存起来,用其他方式解码。

        我这里只是为了能实时看到,所以是用了一个QLabel来显示,首先获取这个控件的句柄:winId(),然后在你想看实时图像的时候调实时预览的接口:CLIENT_RealPlayEx(登录句柄, 通道号, 用于显示图像的控件句柄, 也可以不写默认就是实时监视);

// 实现实时监视功能业务
    // 获取控制台窗口句柄
    // 1.例程中的方法
    // HMODULE hKernel32 = GetModuleHandle("kernel32");
    // GetConsoleWindow = (PROCGETCONSOLEWINDOW)GetProcAddress(hKernel32,"GetConsoleWindow");
    // HWND hWnd = GetConsoleWindow();// NULL;
    // 2.获取qt控件的方法
    HWND hWnd = (HWND)ui->label_RealDisplay->winId();
    //开启实时监视
    int nChannelID = 0; // 预览通道号
    DH_RealPlayType emRealPlayType = DH_RType_Realplay; // 实时监视
    lHandle = CLIENT_RealPlayEx(LoginHandle, nChannelID, hWnd, emRealPlayType);
    QString logInfo = QSC("实时显示开启%1。").arg(lHandle ? QSC("成功") : QSC("失败,错误码[%1]").arg(QString::number(CLIENT_GetLastError(), 16)));
    qDebug() << logInfo;

2.5 断开时释放

        我个人觉得有一个好的习惯是很重要的,就像指针一样,一定要有new 有delete,当然如果你懒得写相应的函数,你也可以把它们写在析构里。

// 关闭预览
    if (lHandle)
    {
        bool lHandleFlag = CLIENT_StopRealPlayEx(lHandle);
        QString logInfo = QSC("实时显示关闭%1。").arg(lHandleFlag ? QSC("成功") : QSC("失败,错误码[%1]").arg(QString::number(CLIENT_GetLastError(), 16)));
        qDebug() << logInfo;
        if(lHandleFlag)
            lHandle = false;
    }
// 退出设备
    if (LoginHandle)
    {
        bool LoginHandleFlag = CLIENT_Logout(LoginHandle);
        QString logInfo = QSC("实时显示关闭%1。").arg(LoginHandleFlag ? QSC("成功") : QSC("失败,错误码[%1]").arg(QString::number(CLIENT_GetLastError(), 16)));
        qDebug() << logInfo;
        if(LoginHandleFlag)
            LoginHandle = false;
    }
// 清理初始化资源
    if (g_bNetSDKInitFlag)
    {
        CLIENT_Cleanup();
        g_bNetSDKInitFlag = false;
    }

2.6 回调函数

        能正常显示的前提还需要一些回调函数,断开重连那几个都一样,你如果需要是连了很多个摄像头,可以在回调函数里把一些信息log出来,我这里暂时是连一个,所以就没打印信息,只是打印了一下调用信息。

//断线回调
void CALLBACK MainWidget::DisConnectFunc(LLONG lLoginID, char *pchDVRIP, LONG nDVRPort, DWORD dwUser)
{
    qDebug() << QSC("断线回调\n");
}
//重连回调
void CALLBACK MainWidget::HaveReConnect(LLONG lLoginID,char *pchDVRIP,LONG nDVRPort,LDWORD dwUser)
{
    qDebug() << QSC("重连回调\n");
}

抓图回调里面可以设置抓图的路径

//抓图回调
void CALLBACK MainWidget::SnapRev(LLONG lLoginID, BYTE *pBuf, UINT RevLen, UINT EncodeType, DWORD CmdSerial, LDWORD dwUser)
{
    qDebug() << QSC("抓图回调\n");
    qDebug() << QSC("抓图句柄:") << lLoginID;
    // if(lLoginID =&
  • 14
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

那个谁_Viktor

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值