基于大华网络摄像头SDK开发抓图工具类(C++)

【前言】

众所周知,大华网络摄像头没有直接提供相应的ROS驱动包,所以我们理论上有两个办法在C++中获取网络摄像头图像:

一是通过OpenCV(FFmpeg)的videocapture类去抓取图像;

二是通过大华官方提供的SDK,自己封装一个抓图工具类。

这里主要讲述第二种方法。

基于大华网络摄像头SDK开发抓图工具类(C++)_第1张图片

【资源】

大华SDK下载地址

supporthttps://support.dahuatech.com/tools/sdkExploit/24

【干货】

1、先搞一个放数据结构的类

#ifndef USERDEFINE_H
#define USERDEFINE_H

#include "dhnetsdk.h"
#include "dhconfigsdk.h"
#include 
#include 

typedef struct
{
  LLONG lRealPlayHandle;
  unsigned long dwStatistic;
} DH_Channel_Info;

typedef struct
{
  LLONG lLoginHandle;
  int nChannelCount;
  char szDevIp[32];
  int nPort;
  char szUserName[32];
  char szPassWord[32];
  DH_Channel_Info channel[16];
} DH_Device_Info;

typedef std::list DEVICE_LIST;
extern DEVICE_LIST g_DeviceList;

typedef std::vector ONE_IMAGE_BUFFER;
extern ONE_IMAGE_BUFFER g_ImageBuffer;

extern bool g_SnapSuccFlag;

#endif

2、再搞一个接口类,用来封装SDK的API

#include "UserDefine.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include 

class DHCamera
{
public:
  DHCamera();
  ~DHCamera();
  bool initSDKClient();
  void initDeviceInfo(DH_Device_Info &stDeviceInfo);
  void loadDeviceInfo();
  void loginDev();
  void grabCamImage(LLONG loginHandle);
  void logoutDev();

public:
  std::map devHandles_map;
};

3、再来看一下类的具体实现吧

#include "DHCamera.h"

DEVICE_LIST g_DeviceList;
ONE_IMAGE_BUFFER g_ImageBuffer;
bool g_SnapSuccFlag = false;
static bool g_bNetSDKInitFlag = false;
static short g_nCmdSerial = 0;

void CALLBACK DisConnectFunc(LLONG lLoginID, char *pchDVRIP, LONG nDVRPort, LDWORD dwUser)
{
  DHCamera* pThis = (DHCamera *)dwUser;
  if(NULL == pThis)
  {
    return;
  }

  printf("Call DisConnectFunc\n");
  printf("lLoginID[0x%x]", lLoginID);
  if (NULL != pchDVRIP)
  {
    printf("pchDVRIP[%s]\n", pchDVRIP);
  }
  printf("nDVRPort[%d]\n", nDVRPort);
  printf("dwUser[%p]\n", dwUser);
  printf("\n");
  return;
}

void CALLBACK HaveReConnect(LLONG lLoginID, char *pchDVRIP, LONG nDVRPort, LDWORD dwUser)
{
  printf("Call HaveReConnect\n");
  printf("lLoginID[0x%x]", lLoginID);
  if (NULL != pchDVRIP)
  {
    printf("pchDVRIP[%s]\n", pchDVRIP);
  }
  printf("nDVRPort[%d]\n", nDVRPort);
  printf("dwUser[%p]\n", dwUser);
  printf("\n");
}

void CALLBACK SnapRev(LLONG lLoginID, BYTE *pBuf, UINT RevLen, UINT EncodeType, DWORD CmdSerial, LDWORD dwUser)
{
  std::vector current_frame(pBuf, pBuf+RevLen);
  g_ImageBuffer.swap(current_frame);
  g_SnapSuccFlag = true;
}

DHCamera::DHCamera()
{
}

DHCamera::~DHCamera()
{
  DEVICE_LIST::iterator it = g_DeviceList.begin();
  while (it != g_DeviceList.end())
  {
    DH_Device_Info *pDeviceInfo = (*it);
    if (pDeviceInfo != nullptr)
    {
      delete pDeviceInfo;
      pDeviceInfo = nullptr;
    }
    it++;
  }
  g_DeviceList.clear();
}

bool DHCamera::initSDKClient()
{
  g_bNetSDKInitFlag = CLIENT_Init(DisConnectFunc, (LDWORD)this);
  CLIENT_SetAutoReconnect(HaveReConnect, 0);
  return g_bNetSDKInitFlag;
}

void DHCamera::initDeviceInfo(DH_Device_Info &stDeviceInfo)
{
  stDeviceInfo.lLoginHandle = 0UL;
  stDeviceInfo.nChannelCount = 0;
  stDeviceInfo.nPort = 0;
  memset(&stDeviceInfo.szDevIp , 0 , sizeof(stDeviceInfo.szDevIp));
  memset(&stDeviceInfo.szUserName , 0 , sizeof(stDeviceInfo.szUserName));
  memset(&stDeviceInfo.szPassWord , 0 , sizeof(stDeviceInfo.szPassWord));
  memset(&stDeviceInfo.channel , 0 , sizeof(stDeviceInfo.channel));
}

void DHCamera::loadDeviceInfo()
{
  DEVICE_LIST::iterator it = g_DeviceList.begin();
  while (it != g_DeviceList.end())
  {
    DH_Device_Info *pDeviceInfo = (*it);
    if (pDeviceInfo != nullptr)
    {
      delete pDeviceInfo;
      pDeviceInfo = nullptr;
    }
    it++;
  }
  g_DeviceList.clear();

  int start_ip = 150;
  int connect_num = 12;
  int port = 37777;

  for(int i = start_ip; i < (start_ip + connect_num); i++)
  {
    DH_Device_Info* device_info = new DH_Device_Info;
    initDeviceInfo(*device_info);
    std::string ip = "192.168.1.";
    strncpy(device_info->szDevIp, (ip+std::to_string(i)).c_str(), sizeof(device_info->szDevIp)-1);
    device_info->nPort = port;
    strncpy(device_info->szUserName, "admin", sizeof(device_info->szUserName)-1);
    strncpy(device_info->szPassWord, "admin123", sizeof(device_info->szPassWord)-1);
    g_DeviceList.push_back(device_info);
  }

  printf("Init Dev's Num : %d\n", g_DeviceList.size());
}

void DHCamera::loginDev()
{
  DEVICE_LIST::iterator it = g_DeviceList.begin();
  while(it != g_DeviceList.end())
  {
    DH_Device_Info *pDeviceInfo = (*it);
    if(pDeviceInfo == NULL)
    {
      it++;
      continue;
    }

    NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY stInparam;
    memset(&stInparam, 0, sizeof(stInparam));
    stInparam.dwSize = sizeof(stInparam);
    strncpy(stInparam.szIP, pDeviceInfo->szDevIp, sizeof(stInparam.szIP) - 1);
    strncpy(stInparam.szPassword, pDeviceInfo->szPassWord, sizeof(stInparam.szPassword) - 1);
    strncpy(stInparam.szUserName, pDeviceInfo->szUserName, sizeof(stInparam.szUserName) - 1);
    stInparam.nPort = pDeviceInfo->nPort;
    stInparam.emSpecCap = EM_LOGIN_SPEC_CAP_TCP;

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

    pDeviceInfo->lLoginHandle = CLIENT_LoginWithHighLevelSecurity(&stInparam, &stOutparam);
    if(pDeviceInfo->lLoginHandle != 0)
    {
      devHandles_map.emplace(pDeviceInfo->szDevIp, pDeviceInfo->lLoginHandle);
      printf("CLIENT_LoginWithHighLevelSecurity %s[%d] Success\n" , pDeviceInfo->szDevIp , pDeviceInfo->nPort);
      usleep(500000);
    }
    else {
      printf("Failed to login IP[%s]\n", pDeviceInfo->szDevIp);
    }
  }
}

void DHCamera::logoutDev()
{
  DEVICE_LIST::iterator it = g_DeviceList.begin();
  while(it != g_DeviceList.end())
  {
    if((*it)->lLoginHandle != 0)
    {
      CLIENT_Logout((*it)->lLoginHandle);
    }
  }
  if (TRUE == g_bNetSDKInitFlag)
  {
    CLIENT_Cleanup();
    g_bNetSDKInitFlag = FALSE;
  }
}

void DHCamera::grabCamImage(long loginHandle)
{
  if (0 == loginHandle)
  {
    return;
  }
  // 设置抓图回调函数
  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 = ++g_nCmdSerial; // 请求序列号,有效值范围 0~65535,超过范围会被截断为 unsigned short
  if (FALSE == CLIENT_SnapPictureEx(loginHandle, &stuSnapParams))
  {
    printf("CLIENT_SnapPictureEx Failed!Last Error[%x]\n", CLIENT_GetLastError());
    return;
  }
  else
  {
    printf("CLIENT_SnapPictureEx succ\n");
  }
}

【后言】

如果这篇博客对你有帮助,就点个赞呗!

你可能感兴趣的:(常用工具,c++,ffmpeg,开发语言)