当前位置: 首页 > article >正文

海康威视豆干型网络相机QT的Demo

        我用的时候海康官网在arm-linux相关SDK没有给DEMO,只在手册里给了参考代码。自己参考SDK提供的手册作了个QT的DEMO版本。

//main.c
#include <QApplication>
#include <QWidget>
#include <QDebug>
#include <QTimer>
#include "HikvisionCamera.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv); // 初始化 Qt 应用程序

    // 创建一个窗口
    QWidget window;
    window.setWindowTitle("Video Preview"); // 设置窗口标题
    window.resize(800, 600); // 设置窗口大小
    window.show(); // 显示窗口

    // 创建海康威视相机对象
    HikvisionCamera camera(&window);

    // 注册设备并登录
    if (!camera.login("192.168.1.224", 8000, "admin", "hbst1888"))
    {
        qDebug() << "Login failed";
        return -1;
    }

    WId Wid = window.winId();//获取窗口句柄
    // 启动预览
    if (!camera.startPreview(1,Wid)) // 通道号为 1
    {
        qDebug() << "Start preview failed";
        return -1;
    }

    // 设置定时器,10 秒后停止预览并退出
    QTimer::singleShot(100000, [&]() {
        camera.stopPreview();
        camera.logout();
        app.quit(); // 退出应用程序
    });

    return app.exec(); // 启动 Qt 事件循环
}
//HikvisionCamera.cpp
#include "HikvisionCamera.h"
#include <QDebug>
#include <QTimer>
#include <QDateTime>
#include "HCNetSDK.h"
#include "LinuxPlayM4.h"

// 实时数据回调函数
void CALLBACK g_RealDataCallBack_V30(
    LONG lRealHandle,       // 实时视频流的句柄,标识当前的视频流会话
    DWORD dwDataType,       // 数据类型,例如视频流数据、音频流数据等
    BYTE *pBuffer,          // 指向数据缓冲区的指针,存储实际的数据
    DWORD dwBufSize,        // 数据缓冲区的大小,单位为字节
    void* dwUser            // 用户自定义数据指针,通常用于传递上下文信息
)
{
    VideoPlayer *player = static_cast<VideoPlayer*>(dwUser); // 获取 VideoPlayer 对象
    if (dwDataType == NET_DVR_STREAMDATA && dwBufSize > 0) // 检查数据类型和大小
    {
        QByteArray frame(reinterpret_cast<char*>(pBuffer), dwBufSize); // 将数据转换为 QByteArray
        emit player->updateVideoFrame(frame); // 发出信号,传递视频帧数据
    }
}

// 异常回调函数
void CALLBACK g_ExceptionCallBack(
    DWORD dwType,           // 异常类型,例如网络异常、重连事件等
    LONG lUserID,           // 用户ID,标识当前的用户会话
    LONG lHandle,           // 相关的句柄,例如登录句柄或实时视频流句柄
    void *pUser             // 用户自定义数据指针,通常用于传递上下文信息
)
{
    switch (dwType) // 根据异常类型处理
    {
    case EXCEPTION_RECONNECT: // 重连事件
        qDebug() << "Reconnect at" << QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");
        break;
    default:
        break;
    }
}

HikvisionCamera::HikvisionCamera(QWidget *parent)
    : lUserID(-1), lRealPlayHandle(-1), lPort(-1), player(new VideoPlayer(parent))
{
    // 初始化海康威视 SDK
    NET_DVR_Init();
    NET_DVR_SetConnectTime(2000, 1); // 设置连接超时时间
    NET_DVR_SetReconnect(10000, true); // 设置自动重连时间
    NET_DVR_SetExceptionCallBack_V30(0, NULL, g_ExceptionCallBack, NULL); // 设置异常回调
}

HikvisionCamera::~HikvisionCamera()
{
    NET_DVR_Cleanup(); // 清理 SDK 资源
    delete player;
}

bool HikvisionCamera::login(const char *ip, int port, const char *username, const char *password)
{
    memset(&struLoginInfo, 0, sizeof(struLoginInfo));
    strcpy(struLoginInfo.sDeviceAddress, ip); // 设备 IP 地址
    struLoginInfo.wPort = port; // 设备端口
    strcpy(struLoginInfo.sUserName, username); // 用户名
    strcpy(struLoginInfo.sPassword, password); // 密码

    lUserID = NET_DVR_Login_V40(&struLoginInfo, &struDeviceInfoV40); // 登录设备
    if (lUserID < 0) // 登录失败
    {
        qDebug() << "Login failed, error code:" << NET_DVR_GetLastError();
        return false;
    }
    return true;
}

void HikvisionCamera::logout()
{
    if (lUserID != -1)
    {
        NET_DVR_Logout(lUserID); // 注销用户
        lUserID = -1;
    }
}

bool HikvisionCamera::startPreview(int channel,WId Wid)
{
    memset(&struPlayInfo, 0, sizeof(struPlayInfo));
    struPlayInfo.hPlayWnd = Wid; // 设置预览窗口句柄
    struPlayInfo.lChannel = channel; // 通道号
    struPlayInfo.dwStreamType = 0; // 流类型
    struPlayInfo.dwLinkMode = 0; // 链接模式
    struPlayInfo.bBlocked = 1; // 阻塞模式

    lRealPlayHandle = NET_DVR_RealPlay_V40(lUserID, &struPlayInfo, g_RealDataCallBack_V30, player); // 启动预览
    if (lRealPlayHandle < 0) // 预览失败
    {
        qDebug() << "NET_DVR_RealPlay_V40 error, error code:" << NET_DVR_GetLastError();
        return false;
    }
    return true;
}

void HikvisionCamera::stopPreview()
{
    if (lRealPlayHandle != -1)
    {
        NET_DVR_StopRealPlay(lRealPlayHandle); // 停止预览
        lRealPlayHandle = -1;
    }
    if (lPort != -1) // 释放播放库资源
    {
        PlayM4_Stop(lPort);
        PlayM4_CloseStream(lPort);
        PlayM4_FreePort(lPort);
        lPort = -1;
    }
}

        针对部分重点代码梳理一下逻辑,

        登陆比较好说,就是设备IP地址、端口号、通过海康的设备检索软件设置的用户名、密码。

bool HikvisionCamera::login(
    const char *ip,         // 设备的 IP 地址
    int port,               // 设备的端口号
    const char *username,   // 登录设备的用户名
    const char *password    // 登录设备的密码
)
{
    memset(&struLoginInfo, 0, sizeof(struLoginInfo)); // 清空登录信息结构体
    strcpy(struLoginInfo.sDeviceAddress, ip); // 设置设备 IP 地址
    struLoginInfo.wPort = port; // 设置设备端口
    strcpy(struLoginInfo.sUserName, username); // 设置用户名
    strcpy(struLoginInfo.sPassword, password); // 设置密码

    lUserID = NET_DVR_Login_V40(&struLoginInfo, &struDeviceInfoV40); // 登录设备
    if (lUserID < 0) // 登录失败
    {
        qDebug() << "Login failed, error code:" << NET_DVR_GetLastError();
        return false;
    }
    return true;
}

        登出的时候直接用登陆时获取到的用户ID进行登出。

void HikvisionCamera::logout()
{
    if (lUserID != -1)
    {
        NET_DVR_Logout(lUserID); // 注销用户
        lUserID = -1;
    }
}

        开始预览,

        窗口句柄用于指定在哪个窗口显示视频流。

        设备通道号用于指定从哪个通道获取视频流。通道号通常从1开始,有多少通道取决于设备的配置。

        视频流类型,通常有 0主码流、1子码流

        主码流是主视频流,分辨率较高。

        子码流是辅助视频流,分辨率较低,适合网络传输。

        链接模式有0 TCP模式和1 UDP模式

        阻塞模式,0关闭,1开启。实时预览是否阻塞当前线程。

bool HikvisionCamera::startPreview(int channel,WId Wid)
{
    memset(&struPlayInfo, 0, sizeof(struPlayInfo));
    struPlayInfo.hPlayWnd = Wid; // 设置预览窗口句柄
    struPlayInfo.lChannel = channel; // 通道号
    struPlayInfo.dwStreamType = 0; // 流类型
    struPlayInfo.dwLinkMode = 0; // 链接模式
    struPlayInfo.bBlocked = 1; // 阻塞模式

    lRealPlayHandle = NET_DVR_RealPlay_V40(lUserID, &struPlayInfo, g_RealDataCallBack_V30, player); // 启动预览
    if (lRealPlayHandle < 0) // 预览失败
    {
        qDebug() << "NET_DVR_RealPlay_V40 error, error code:" << NET_DVR_GetLastError();
        return false;
    }
    return true;
}


http://www.kler.cn/a/536209.html

相关文章:

  • 当代编程语言的新思路:废除独立关键字,使用时加标志
  • MySQL三大日志——binlog、redoLog、undoLog详解
  • PySpark学习笔记5-SparkSQL
  • PlanLLM: 首个支持开放词汇与封闭集任务的跨模态视频程序规划框架
  • 网络工程师 (21)网络的性能
  • 98.2 AI量化开发:基于DeepSeek打造个人专属金融消息面-AI量化分析师(理论+全套Python代码)
  • 【学习总结|DAY036】Vue工程化+ElementPlus
  • 华为小艺助手接入DeepSeek,升级鸿蒙HarmonyOS NEXT即可体验
  • Linux中DataX使用第三期
  • Java 8的Stream API
  • 栈和队列的实现(C语言)
  • 解决aspose将Excel转成PDF中文变成方框的乱码问题
  • esp32 udp 客户端 广播
  • 【Elasticsearch】nested聚合
  • Day67:类的继承
  • 树莓派5添加摄像头 在C++下调用opencv
  • Junit5使用教程(6)--高级特性2
  • HTML学习之CSS三种引入方式
  • 基于JavaWeb开发的java Springboot实现教务管理系统
  • 介绍10个比较优秀好用的Qt相关的开源库
  • Linux后台运行进程
  • 网络安全 | 什么是XSS跨站脚本攻击?
  • 如何利用 Python 爬虫按关键字搜索淘宝商品
  • C++基础系列【5】namespace using
  • JAVA异步的TCP 通讯-客户端
  • 【STM32系列】利用MATLAB配合ARM-DSP库设计FIR数字滤波器(保姆级教程)