• Qt 调用海康威视的SDK进行视频预览及云台控制


    特别说明:个人笔记,不惜勿喷。

      Qt获取海康摄像头图像方法很多,比如可以只用RTSP的方式直接拉流获取。但是RTSP拉流的方式我也尝试过,需要用到FFMPEG,由于这个库东西比较多,而且里面很多流程需要自己去做解析,程序员本就是图方便和高效,与其去折腾,还不如直接用官方提供的SDK。这样省很多事情。

     海康SDK开发心得:在预览图像的时候图像时延是非常低的,相比ffmpeg的rtsp要低很多,因此如果项目对于时延要去高的地方可以考虑用sdk来试试。

      于是乎,自己研究了下,发现比较简单,此处仅作笔记,无技术含量。

    1、首先工程文件添加海康SDK的库和头文件

    1. LIBS += -L$$PWD/hiklib/lib/ -lHCNetSDK
    2. INCLUDEPATH += $$PWD/hiklib/include
    3. DEPENDPATH += $$PWD/hiklib/include

    2、登录摄像头

    1. NET_DVR_Init();
    2. NET_DVR_SetConnectTime(2000, 1);
    3. NET_DVR_SetReconnect(10000, true);
    4. NET_DVR_USER_LOGIN_INFO struLoginInfo;
    5. NET_DVR_DEVICEINFO_V40 struDeviceInfoV40;
    6. memset(&struLoginInfo, 0x00, sizeof(NET_DVR_USER_LOGIN_INFO));
    7. memset(&struDeviceInfoV40, 0x00, sizeof(NET_DVR_DEVICEINFO_V40));
    8. struLoginInfo.bUseAsynLogin = 0; // 同步登录方式
    9. strcpy(struLoginInfo.sDeviceAddress, "192.168.0.143"); // 设备IP地址
    10. struLoginInfo.wPort = 8000 ; // 设备服务端口
    11. strcpy_s(struLoginInfo.sUserName, "admin"); // 设备登录用户名
    12. strcpy_s(struLoginInfo.sPassword, "123456"); // 设备登录密码
    13. m_userId = NET_DVR_Login_V40(&struLoginInfo, &struDeviceInfoV40);
    14. if (m_userId < 0)
    15. {
    16. qDebug() << "登录失败" << m_userId << NET_DVR_GetErrorMsg();
    17. }

    3、登录成功后就可以直接启动图像预览了。

    1. NET_DVR_PREVIEWINFO struPreviewInfo;
    2. memset(&struPreviewInfo, 0x00, sizeof(NET_DVR_PREVIEWINFO));
    3. struPreviewInfo.lChannel = 1; // 通道id
    4. struPreviewInfo.hPlayWnd = (HWND)ui->labelPreview->winId();
    5. struPreviewInfo.dwStreamType = 0; // 码流类型: 0-主码流
    6. struPreviewInfo.dwLinkMode = 0; // 链接方式: 0- TCP方式
    7. struPreviewInfo.bBlocked = 0; // 0 - 非阻塞取流,1 - 阻塞取流
    8. m_previewHandle = NET_DVR_RealPlay_V40(m_userId, &struPreviewInfo, NULL, NULL);

    4、云台控制 

    1. #define START 0
    2. #define STOP 1
    3. NET_DVR_PTZControl(m_previewHandle, TILT_UP, START);
    4. NET_DVR_PTZControl(m_previewHandle, TILT_UP, STOP);
    5. /* 下 */
    6. NET_DVR_PTZControl(m_previewHandle, TILT_DOWN, START);
    7. NET_DVR_PTZControl(m_previewHandle, TILT_DOWN, STOP);
    8. /* 其他方向可以自行查看头文件,方法一样 */

    5、辅助功能:网络摄像头局域网扫描通信协议,方便在不知道摄像头ip的情况下进行

    通过UDP报文广播的方式扫描在线摄像头

    1. QString strData = QString("<?xml version=\"1.0\" encoding=\"utf-8\"?><Probe><Uuid>");
    2. m_strUuid = QUuid::createUuid().toString(QUuid::WithoutBraces).toUpper();
    3. strData += m_strUuid;
    4. strData += "</Uuid><Types>inquiry</Types></Probe>";
    5. qint64 len = m_udpSocket->writeDatagram(strData.toLatin1(), QHostAddress("239.255.255.250"), 37020);
    6. qDebug() << "==>" << len << strData;

    协议解析:

    1. void ScanIPCameras::sltUdpSocketRead()
    2. {
    3. QByteArray byData;
    4. // qDebug() << "udp recv" << m_udpSocket->pendingDatagramSize();
    5. while (m_udpSocket->hasPendingDatagrams()) {
    6. #if (QT_VERSION > QT_VERSION_CHECK(5, 8, 0))
    7. QNetworkDatagram datagram = m_udpSocket->receiveDatagram();
    8. QHostAddress host = datagram.senderAddress();
    9. byData += datagram.data();
    10. #else
    11. QByteArray datagram;
    12. datagram.resize(m_udpSocket->pendingDatagramSize());
    13. m_udpSocket->readDatagram(datagram.data(), datagram.size());
    14. byData += datagram;
    15. #endif
    16. }
    17. parseXmlData(byData);
    18. }

    解析如下:

    1. void ScanIPCameras::parseXmlData(const QByteArray &_byContent)
    2. {
    3. QDomDocument document;
    4. QString error;
    5. int row = 0, column = 0;
    6. if (!document.setContent(_byContent, false, &error, &row, &column))
    7. {
    8. return;
    9. }
    10. if (document.isNull())
    11. {
    12. return;
    13. }
    14. QDomElement root = document.documentElement();
    15. for(QDomNode node = root.firstChild(); !node.isNull(); node = node.nextSibling())
    16. {
    17. QDomElement e = node.toElement();
    18. QString tag = node.nodeName();
    19. QString value = e.text();
    20. if ("Uuid" == tag) {
    21. qDebug() << "value" << value;
    22. qDebug() << "Uuid " << m_strUuid;
    23. m_strUuid = value;
    24. }
    25. else if ("DeviceDescription" == tag) {
    26. }
    27. else if ("IPv4Address" == tag) {
    28. emit signalCamera(value);
    29. emit signalNotify(QString("摄像头扫描: 扫描完成,发现设备[%1]!~").arg(value));
    30. }
    31. else if ("CommandPort" == tag) {
    32. }
    33. else if ("HttpPort" == tag) {
    34. }
    35. else if ("DHCP" == tag) {
    36. }
    37. else if ("DeviceSN" == tag) {
    38. }
    39. else {
    40. qDebug() << tag << value;
    41. }
    42. }
    43. }

    效果图:

     

  • 相关阅读:
    二叉树的遍历
    R语言实现样本量的估算(2)
    Talk预告 | 北京大学杨灵:扩散生成模型的方法、关联与应用
    新生儿常见问题>奶癣
    C#是否应该限制链式重载的设计模式?
    Python生成二维码
    xshell的基本命令
    C++学习笔记总结练习:多态与虚函数
    系统架构师备考倒计时24天(每日知识点)
    iOS开发之机器学习框架MediaPipe(5)
  • 原文地址:https://blog.csdn.net/nigoole/article/details/125633580