众所周知,海康的摄像头sdk较为完善,但是对于新手来说还是有点麻烦。

  今天写一篇随笔给大家展示下怎么控制海康摄像头的云台(前提是有ptz云台设备)

  1、sdk准备

    

  本文基于C#的frame来开发一个ptz控制的demo,上图是海康sdk提供的动态库cs文件,通过dllimport来提取封装的函数。主要使用NET_DVR_PTZControlWithSpeed_Other来控制云台。

  其中虚线框的流程是可选部分,不会影响其他流程和模块的功能使用。按实现功能的不同可以分成十 个模块,实现每个模块的功能时初始化 SDK、用户注册设备、注销设备和释放 SDK 资源这 4 个流程是必不 可少的,解码器功能模块和行为分析功能模块是针对解码器和智能设备的,在该文档里我们不做描述。

用户注册设备(NET_DVR_Login_V30):实现用户的注册功能,注册成功后,返回的用户 ID 作为其他功 能操作的唯一标识,SDK 允许最大注册用户数为 512 个。网络摄像机和网络球机允许有 16 个注册用户 名,而且同时最多允许 128 个用户注册。

1.1用户注册及链接摄像头设备

  1. private bool m_bInitSDK = false;
  2. private bool m_bRecord = false;
  3. private uint iLastErr = 0;
  4. private Int32 m_lUserID = -1;
  5. private Int32 m_lRealHandle = -1;
  6. private string str1;
  7. private string str2;
  8. private Int32 i = 0;
  9. private Int32 m_lTree = 0;
  10. private string str;
  11. private long iSelIndex = 0;
  12. private uint dwAChanTotalNum = 0;
  13. private uint dwDChanTotalNum = 0;
  14. private Int32 m_lPort = -1;
  15. private IntPtr m_ptrRealHandle;
  16. private int[] iIPDevID = new int[96];
  17. private int[] iChannelNum = new int[96];
  18.  
  19. private CHCNetSDK.REALDATACALLBACK RealData = null;
  20. public CHCNetSDK.NET_DVR_DEVICEINFO_V30 DeviceInfo;
  21. public CHCNetSDK.NET_DVR_IPPARACFG_V40 m_struIpParaCfgV40;
  22. public CHCNetSDK.NET_DVR_STREAM_MODE m_struStreamMode;
  23. public CHCNetSDK.NET_DVR_IPCHANINFO m_struChanInfo;
  24. public CHCNetSDK.NET_DVR_PU_STREAM_URL m_struStreamURL;
  25. public CHCNetSDK.NET_DVR_IPCHANINFO_V40 m_struChanInfoV40;
  26. public delegate void MyDebugInfo(string str);
  27. CHCNetSDK.NET_DVR_PREVIEWINFO lpPreviewInfo = new CHCNetSDK.NET_DVR_PREVIEWINFO();
  28.  
  29. public MainForm()
  30. {
  31. InitializeComponent();
  32. m_bInitSDK = CHCNetSDK.NET_DVR_Init();
  33. if (m_bInitSDK == false)
  34. {
  35. MessageBox.Show("NET_DVR_Init error!");
  36. return;
  37. }
  38. else
  39. {
  40. //保存SDK日志 To save the SDK log
  41. CHCNetSDK.NET_DVR_SetLogToFile(3, @"./SdkLog", true);
  42.  
  43. //comboBoxView.SelectedIndex = 0;
  44.  
  45. //for (int i = 0; i < 64; i++)
  46. //{
  47. // iIPDevID[i] = -1;
  48. // iChannelNum[i] = -1;
  49. //}
  50. }
  51.  
  52. }
  53.  
  54. public void ListIPChannel(Int32 iChanNo, byte byOnline, int byIPID)
  55. {
  56. str1 = String.Format("IPCamera {0}", iChanNo);
  57. m_lTree++;
  58.  
  59. if (byIPID == 0)
  60. {
  61. str2 = "X"; //通道空闲,没有添加前端设备 the channel is idle
  62. }
  63. else
  64. {
  65. if (byOnline == 0)
  66. {
  67. str2 = "offline"; //通道不在线 the channel is off-line
  68. }
  69. else
  70. str2 = "online"; //通道在线 The channel is on-line
  71. }
  72.  
  73. //listViewIPChannel.Items.Add(new ListViewItem(new string[] { str1, str2 }));//将通道添加到列表中 add the channel to the list
  74. }
  75. public void ListAnalogChannel(Int32 iChanNo, byte byEnable)
  76. {
  77. str1 = String.Format("Camera {0}", iChanNo);
  78. m_lTree++;
  79.  
  80. if (byEnable == 0)
  81. {
  82. str2 = "Disabled"; //通道已被禁用 This channel has been disabled
  83. }
  84. else
  85. {
  86. str2 = "Enabled"; //通道处于启用状态 This channel has been enabled
  87. }
  88.  
  89. //listViewIPChannel.Items.Add(new ListViewItem(new string[] { str1, str2 }));//将通道添加到列表中 add the channel to the list
  90. }
  91. public void InfoIPChannel()
  92. {
  93. uint dwSize = (uint)Marshal.SizeOf(m_struIpParaCfgV40);
  94.  
  95. IntPtr ptrIpParaCfgV40 = Marshal.AllocHGlobal((Int32)dwSize);
  96. Marshal.StructureToPtr(m_struIpParaCfgV40, ptrIpParaCfgV40, false);
  97.  
  98. uint dwReturn = 0;
  99. int iGroupNo = 0; //该Demo仅获取第一组64个通道,如果设备IP通道大于64路,需要按组号0~i多次调用NET_DVR_GET_IPPARACFG_V40获取
  100.  
  101. if (!CHCNetSDK.NET_DVR_GetDVRConfig(m_lUserID, CHCNetSDK.NET_DVR_GET_IPPARACFG_V40, iGroupNo, ptrIpParaCfgV40, dwSize, ref dwReturn))
  102. {
  103. iLastErr = CHCNetSDK.NET_DVR_GetLastError();
  104. str = "NET_DVR_GET_IPPARACFG_V40 failed, error code= " + iLastErr;
  105. //获取IP资源配置信息失败,输出错误号 Failed to get configuration of IP channels and output the error code
  106. }
  107. else
  108. {
  109.  
  110. m_struIpParaCfgV40 = (CHCNetSDK.NET_DVR_IPPARACFG_V40)Marshal.PtrToStructure(ptrIpParaCfgV40, typeof(CHCNetSDK.NET_DVR_IPPARACFG_V40));
  111.  
  112. for (i = 0; i < dwAChanTotalNum; i++)
  113. {
  114. ListAnalogChannel(i + 1, m_struIpParaCfgV40.byAnalogChanEnable[i]);
  115. iChannelNum[i] = i + (int)DeviceInfo.byStartChan;
  116. }
  117.  
  118. byte byStreamType = 0;
  119. uint iDChanNum = 64;
  120.  
  121. if (dwDChanTotalNum < 64)
  122. {
  123. iDChanNum = dwDChanTotalNum; //如果设备IP通道小于64路,按实际路数获取
  124. }
  125.  
  126. for (i = 0; i < iDChanNum; i++)
  127. {
  128. iChannelNum[i + dwAChanTotalNum] = i + (int)m_struIpParaCfgV40.dwStartDChan;
  129. byStreamType = m_struIpParaCfgV40.struStreamMode[i].byGetStreamType;
  130.  
  131. dwSize = (uint)Marshal.SizeOf(m_struIpParaCfgV40.struStreamMode[i].uGetStream);
  132. switch (byStreamType)
  133. {
  134. //目前NVR仅支持直接从设备取流 NVR supports only the mode: get stream from device directly
  135. case 0:
  136. IntPtr ptrChanInfo = Marshal.AllocHGlobal((Int32)dwSize);
  137. Marshal.StructureToPtr(m_struIpParaCfgV40.struStreamMode[i].uGetStream, ptrChanInfo, false);
  138. m_struChanInfo = (CHCNetSDK.NET_DVR_IPCHANINFO)Marshal.PtrToStructure(ptrChanInfo, typeof(CHCNetSDK.NET_DVR_IPCHANINFO));
  139.  
  140. //列出IP通道 List the IP channel
  141. ListIPChannel(i + 1, m_struChanInfo.byEnable, m_struChanInfo.byIPID);
  142. iIPDevID[i] = m_struChanInfo.byIPID + m_struChanInfo.byIPIDHigh * 256 - iGroupNo * 64 - 1;
  143.  
  144. Marshal.FreeHGlobal(ptrChanInfo);
  145. break;
  146. case 4:
  147. IntPtr ptrStreamURL = Marshal.AllocHGlobal((Int32)dwSize);
  148. Marshal.StructureToPtr(m_struIpParaCfgV40.struStreamMode[i].uGetStream, ptrStreamURL, false);
  149. m_struStreamURL = (CHCNetSDK.NET_DVR_PU_STREAM_URL)Marshal.PtrToStructure(ptrStreamURL, typeof(CHCNetSDK.NET_DVR_PU_STREAM_URL));
  150.  
  151. //列出IP通道 List the IP channel
  152. ListIPChannel(i + 1, m_struStreamURL.byEnable, m_struStreamURL.wIPID);
  153. iIPDevID[i] = m_struStreamURL.wIPID - iGroupNo * 64 - 1;
  154.  
  155. Marshal.FreeHGlobal(ptrStreamURL);
  156. break;
  157. case 6:
  158. IntPtr ptrChanInfoV40 = Marshal.AllocHGlobal((Int32)dwSize);
  159. Marshal.StructureToPtr(m_struIpParaCfgV40.struStreamMode[i].uGetStream, ptrChanInfoV40, false);
  160. m_struChanInfoV40 = (CHCNetSDK.NET_DVR_IPCHANINFO_V40)Marshal.PtrToStructure(ptrChanInfoV40, typeof(CHCNetSDK.NET_DVR_IPCHANINFO_V40));
  161.  
  162. //列出IP通道 List the IP channel
  163. ListIPChannel(i + 1, m_struChanInfoV40.byEnable, m_struChanInfoV40.wIPID);
  164. iIPDevID[i] = m_struChanInfoV40.wIPID - iGroupNo * 64 - 1;
  165.  
  166. Marshal.FreeHGlobal(ptrChanInfoV40);
  167. break;
  168. default:
  169. break;
  170. }
  171. }
  172. }
  173. Marshal.FreeHGlobal(ptrIpParaCfgV40);
  174.  
  175. }

   上面展示的是设备注册链接时要申请的变量;接下来开始链接,这里用一个button去实现用户连接的功能:

  1. private void button1_Click(object sender, EventArgs e)
  2. {
  3. if (m_lUserID < 0)
  4. {
  5. string DVRIPAddress = tb_IP.Text; //设备IP地址或者域名 Device IP
  6. Int16 DVRPortNumber = Int16.Parse(tb_Port.Text);//设备服务端口号 Device Port
  7. string DVRUserName = tb_ID.Text;//设备登录用户名 User name to login
  8. string DVRPassword = tb_Pwd.Text;//设备登录密码 Password to login
  9.  
  10. //登录设备 Login the device
  11. m_lUserID = CHCNetSDK.NET_DVR_Login_V30(DVRIPAddress, DVRPortNumber, DVRUserName, DVRPassword, ref DeviceInfo);
  12. if (m_lUserID < 0)
  13. {
  14. iLastErr = CHCNetSDK.NET_DVR_GetLastError();
  15. str = "NET_DVR_Login_V30 failed, error code= " + iLastErr; //登录失败,输出错误号 Failed to login and output the error code
  16. return;
  17. }
  18. else
  19. {
  20. //登录成功
  21. button1.Text = "断开";
  22.  
  23. dwAChanTotalNum = (uint)DeviceInfo.byChanNum;
  24. dwDChanTotalNum = (uint)DeviceInfo.byIPChanNum + 256 * (uint)DeviceInfo.byHighDChanNum;
  25. if (dwDChanTotalNum > 0)
  26. {
  27. InfoIPChannel();
  28. }
  29. else
  30. {
  31. for (i = 0; i < dwAChanTotalNum; i++)
  32. {
  33. ListAnalogChannel(i + 1, 1);
  34. iChannelNum[i] = i + (int)DeviceInfo.byStartChan;
  35. }
  36.  
  37. //comboBoxView.SelectedItem = 1;
  38. // MessageBox.Show("This device has no IP channel!");
  39. }
  40. }
  41.  
  42. }
  43. else
  44. {
  45. //注销登录 Logout the device
  46. if (m_lRealHandle >= 0)
  47. {
  48. m_lUserID = -1;
  49. button1.Text = "连接相机";
  50. return;
  51. }
  52.  
  53. if (!CHCNetSDK.NET_DVR_Logout(m_lUserID))
  54. {
  55. iLastErr = CHCNetSDK.NET_DVR_GetLastError();
  56. str = "NET_DVR_Logout failed, error code= " + iLastErr;
  57. return;
  58. }
  59. //listViewIPChannel.Items.Clear();//清空通道列表 Clean up the channel list
  60. m_lUserID = -1;
  61. button1.Text = "连接相机";
  62. }
  63.  
  64. if (m_lRealHandle < 0)
  65. {
  66. //lpPreviewInfo.hPlayWnd = RealPlayWnd.Handle;//预览窗口 live view window
  67. lpPreviewInfo.lChannel = iChannelNum[(int)iSelIndex];//预览的设备通道 the device channel number
  68. lpPreviewInfo.dwStreamType = 0;//码流类型:0-主码流,1-子码流,2-码流3,3-码流4,以此类推
  69. lpPreviewInfo.dwLinkMode = 0;//连接方式:0- TCP方式,1- UDP方式,2- 多播方式,3- RTP方式,4-RTP/RTSP,5-RSTP/HTTP
  70. lpPreviewInfo.bBlocked = true; //0- 非阻塞取流,1- 阻塞取流
  71. lpPreviewInfo.dwDisplayBufNum = 15; //播放库显示缓冲区最大帧数
  72.  
  73. IntPtr pUser = IntPtr.Zero;//用户数据 user data
  74.  
  75. //if (comboBoxView.SelectedIndex == 0)
  76. //{
  77. //打开预览 Start live view
  78. m_lRealHandle = CHCNetSDK.NET_DVR_RealPlay_V40(m_lUserID, ref lpPreviewInfo, null/*RealData*/, pUser);
  79. //}
  80. //else
  81. //{
  82. // lpPreviewInfo.hPlayWnd = IntPtr.Zero;//预览窗口 live view window
  83. // m_ptrRealHandle = RealPlayWnd.Handle;
  84. // RealData = new CHCNetSDK.REALDATACALLBACK(RealDataCallBack);//预览实时流回调函数 real-time stream callback function
  85. // m_lRealHandle = CHCNetSDK.NET_DVR_RealPlay_V40(m_lUserID, ref lpPreviewInfo, RealData, pUser);
  86. //}
  87.  
  88. if (m_lRealHandle < 0)
  89. {
  90. iLastErr = CHCNetSDK.NET_DVR_GetLastError();
  91. str = "NET_DVR_RealPlay_V40 failed, error code= " + iLastErr; //预览失败,输出错误号 failed to start live view, and output the error code.
  92. return;
  93. }
  94. else
  95. {
  96. ////预览成功
  97. //DebugInfo("NET_DVR_RealPlay_V40 succ!");
  98. //btnPreview.Text = "Stop View";
  99. MessageBox.Show("连接成功!");
  100. }
  101. }
  102. return;
  103. }

  到这里没报错的话就说明连接上了

1.2 控制云台

上一步时连接设备,注意:我们本次要做的时不预览画面单独控制云台!

需要用到:CHCNetSDK.NET_DVR_PTZControlWithSpeed_Other(m_lRealHandle, lpPreviewInfo.lChannel, 21, 0, 15);

解释:

CHCNetSDK.NET_DVR_PTZControlWithSpeed_Other(m_lRealHandle, lpPreviewInfo.lChannel, 21, 0, 15);//示例

云台控制指令如图:

大家有需要可以试一下,练练手!

海康PTZ云台摄像头调试之直接控制云台(C#)的更多相关文章

  1. 通过ISAPI http协议控制海康摄像头

    一直用海康的SDK进行摄像头控制,但有时候非常不灵活,必须有X86的主机,在嵌入式上面就不行,通过写一个HTTPCLIENT可以通过ISAPI来控制海康的摄像头. 代码如下:git@github.co ...

  2. Java 实现 海康摄像头抓拍图像 Windows、Linux

    先抱怨一下,打死都想不到,海康的摄像头SDK居然是一个Java类,还有必须的两个jar包(jna.jar,examples.jar).鬼能想得到会这么命名. 下面开始吧. Windows 把从官网下载 ...

  3. 用libevent写的海康摄像头rtsp客户端

    之前一直使用live555作为RTSP的客户端,但其框架臃肿,虽然支持各种格式,但实际中并没有这些需求,关键是其注重于格式的解析,却不注重网络IO,单线程下性能也不高,重新用libevent编写rts ...

  4. iNeuOS工业互联平台,WEB组态(iNeuView)集成rtmp和websocket视频元件,支持海康、大华等摄像头实时显示视频

    目       录 1.      概述... 1 2.      平台演示... 2 3.      硬件摄像头... 2 4.      视频流协议转换管理... 2 5.      组态视频元件 ...

  5. 海康摄像头配置固定IP

    前言 首先要海康设备连接好网线,电脑客户端跟海康设备在同一个局域网络. 1.直接在海康网站下载SADP工具软件,安装SADP工具,如图所示: 2.安装成功后,桌面的出现设备网络搜索, 面板介绍:这里将 ...

  6. 海康,睿网设备SDK调试

    引入 外部dll  DllImport [DllImport(@"../bin/HCNetSDK.dll")] 问题1: 找不到模块.... 解决:  [DllImport(@&q ...

  7. 海康SDK编程指南(C#二次开发版本)

    海康SDK编程指南 目前使用的海康SDK包括IPC_SDK(硬件设备),Plat_SDK(平台),其中两套SDK都需单独调用海康播放库PlayCtrl.dll来解码视频流,返回视频信息和角度信息.本文 ...

  8. 海康SDK编程指南

    转至心澄欲遣 目前使用的海康SDK包括IPC_SDK(硬件设备),Plat_SDK(平台),其中两套SDK都需单独调用海康播放库PlayCtrl.dll来解码视频流,返回视频信息和角度信息.本文仅对视 ...

  9. 海康网络摄像机YV12转换为BGR,由opencv Mat显示 (转)

    我使用的是海康DS-2CD852MF-E, 200万,网络摄像机,已经比较老了,不过SDK在海康官网下载的,开发流程都差不多. 海康摄像机回调解码后的视频数据格式为YV12,顺便说一下YV12的数据格 ...

随机推荐

  1. CentOS7中安装pip的方法

    1.安装epel-release [root@localhost ~]# yum -y install epel-release 2.安装python-pip [root@localhost ~]# ...

  2. win11系统设置笔记本合盖上不休眠

    第一步.打开控制面板 第二步.打开控制面板 第三步.打开电源选项 第四步.如下图操作即可

  3. 【洛谷】P1067 多项式输出

    原题链接:P1067 多项式输出 题目分析:学长推荐的OJ网站 --洛谷,发现挺好用的还可以下载提交出错的数据. 废话就不多说了,这道题属于基础题.提交出错主要是因为一些小细节不到位,这里就不一一赘述 ...

  4. RootersCTF2019 I ♥ Flask

    最近也是一直在做ssti方面的题目,我发现了两款比较好用的工具,一个是arjun(用来探测参数),另一个是Tplmap(用来探测ssti漏洞),我们这里以一道题目为例来演示一下 题目 我们拿到题目 分 ...

  5. 创建VS Code 扩展插件

    VS Code提供了强大的扩展功能,我们可以通过开发插件实现自己的业务模型编辑器.这里我们快速介绍一下插件的创建.开发和发布过程. 创建插件开发模板 首先需要确认系统中安装了node.js,并且可以使 ...

  6. MCU软件最佳实践——使用printf打印数据

    在mcu上开发应用时,使用串口打印调试信息是最常用的调试手段之一.printf是c标准库提供的函数,可以方便输出格式化的信息.但针对不同的mcu芯片,printf函数要能正常工作,需要做一些移植和适配 ...

  7. Web开发之HTTP协议

    HTTP响应消息 一个HTTP响应代表服务器向客户端回送的数据. 一个完整的HTTP响应包括如下内容: 一个状态行.若干消息头.以及响应正文,其中的一些消息头和正文都是可选的,消息头和正文内容之间要用 ...

  8. ajax的核心

    <script> // ajax 简称(a 代表异步 j 代表javascript a 代表 and x 代表xml--是一种带有标签的数据格式,被json取代了) //ajax 是异步对 ...

  9. golang中往脚本传递参数的两种用法os.Args和flag

    1. os.Args package main import ( "fmt" "os" ) func main() { // 执行:./demo.exe 127 ...

  10. golang中结构体中的嵌套

    package main import "fmt" type Base struct { name string } func (b *Base) m1() int { retur ...