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

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

cpp 复制代码
//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 事件循环
}
cpp 复制代码
//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地址、端口号、通过海康的设备检索软件设置的用户名、密码。

cpp 复制代码
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进行登出。

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

开始预览,

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

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

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

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

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

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

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

cpp 复制代码
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;
}
相关推荐
用户805533698033 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner3 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz8 天前
QML Hello World 入门示例
qt
xcyxiner11 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner12 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner12 天前
DicomViewer (添加模型类)3
qt
xcyxiner13 天前
DicomViewer (目录调整) 2
qt
xcyxiner13 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
胖咕噜的稞达鸭15 天前
如何写好一个skill
人工智能·数码相机
Hello-FPGA15 天前
CameraLink相机模拟器 信号源加速激光雷达系统算法开发
数码相机