海康PTZ云台摄像头调试之直接控制云台(C#)
众所周知,海康的摄像头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用户注册及链接摄像头设备
private bool m_bInitSDK = false;
private bool m_bRecord = false;
private uint iLastErr = 0;
private Int32 m_lUserID = -1;
private Int32 m_lRealHandle = -1;
private string str1;
private string str2;
private Int32 i = 0;
private Int32 m_lTree = 0;
private string str;
private long iSelIndex = 0;
private uint dwAChanTotalNum = 0;
private uint dwDChanTotalNum = 0;
private Int32 m_lPort = -1;
private IntPtr m_ptrRealHandle;
private int[] iIPDevID = new int[96];
private int[] iChannelNum = new int[96]; private CHCNetSDK.REALDATACALLBACK RealData = null;
public CHCNetSDK.NET_DVR_DEVICEINFO_V30 DeviceInfo;
public CHCNetSDK.NET_DVR_IPPARACFG_V40 m_struIpParaCfgV40;
public CHCNetSDK.NET_DVR_STREAM_MODE m_struStreamMode;
public CHCNetSDK.NET_DVR_IPCHANINFO m_struChanInfo;
public CHCNetSDK.NET_DVR_PU_STREAM_URL m_struStreamURL;
public CHCNetSDK.NET_DVR_IPCHANINFO_V40 m_struChanInfoV40;
public delegate void MyDebugInfo(string str);
CHCNetSDK.NET_DVR_PREVIEWINFO lpPreviewInfo = new CHCNetSDK.NET_DVR_PREVIEWINFO(); public MainForm()
{
InitializeComponent();
m_bInitSDK = CHCNetSDK.NET_DVR_Init();
if (m_bInitSDK == false)
{
MessageBox.Show("NET_DVR_Init error!");
return;
}
else
{
//保存SDK日志 To save the SDK log
CHCNetSDK.NET_DVR_SetLogToFile(3, @"./SdkLog", true); //comboBoxView.SelectedIndex = 0; //for (int i = 0; i < 64; i++)
//{
// iIPDevID[i] = -1;
// iChannelNum[i] = -1;
//}
} } public void ListIPChannel(Int32 iChanNo, byte byOnline, int byIPID)
{
str1 = String.Format("IPCamera {0}", iChanNo);
m_lTree++; if (byIPID == 0)
{
str2 = "X"; //通道空闲,没有添加前端设备 the channel is idle
}
else
{
if (byOnline == 0)
{
str2 = "offline"; //通道不在线 the channel is off-line
}
else
str2 = "online"; //通道在线 The channel is on-line
} //listViewIPChannel.Items.Add(new ListViewItem(new string[] { str1, str2 }));//将通道添加到列表中 add the channel to the list
}
public void ListAnalogChannel(Int32 iChanNo, byte byEnable)
{
str1 = String.Format("Camera {0}", iChanNo);
m_lTree++; if (byEnable == 0)
{
str2 = "Disabled"; //通道已被禁用 This channel has been disabled
}
else
{
str2 = "Enabled"; //通道处于启用状态 This channel has been enabled
} //listViewIPChannel.Items.Add(new ListViewItem(new string[] { str1, str2 }));//将通道添加到列表中 add the channel to the list
}
public void InfoIPChannel()
{
uint dwSize = (uint)Marshal.SizeOf(m_struIpParaCfgV40); IntPtr ptrIpParaCfgV40 = Marshal.AllocHGlobal((Int32)dwSize);
Marshal.StructureToPtr(m_struIpParaCfgV40, ptrIpParaCfgV40, false); uint dwReturn = 0;
int iGroupNo = 0; //该Demo仅获取第一组64个通道,如果设备IP通道大于64路,需要按组号0~i多次调用NET_DVR_GET_IPPARACFG_V40获取 if (!CHCNetSDK.NET_DVR_GetDVRConfig(m_lUserID, CHCNetSDK.NET_DVR_GET_IPPARACFG_V40, iGroupNo, ptrIpParaCfgV40, dwSize, ref dwReturn))
{
iLastErr = CHCNetSDK.NET_DVR_GetLastError();
str = "NET_DVR_GET_IPPARACFG_V40 failed, error code= " + iLastErr;
//获取IP资源配置信息失败,输出错误号 Failed to get configuration of IP channels and output the error code
}
else
{ m_struIpParaCfgV40 = (CHCNetSDK.NET_DVR_IPPARACFG_V40)Marshal.PtrToStructure(ptrIpParaCfgV40, typeof(CHCNetSDK.NET_DVR_IPPARACFG_V40)); for (i = 0; i < dwAChanTotalNum; i++)
{
ListAnalogChannel(i + 1, m_struIpParaCfgV40.byAnalogChanEnable[i]);
iChannelNum[i] = i + (int)DeviceInfo.byStartChan;
} byte byStreamType = 0;
uint iDChanNum = 64; if (dwDChanTotalNum < 64)
{
iDChanNum = dwDChanTotalNum; //如果设备IP通道小于64路,按实际路数获取
} for (i = 0; i < iDChanNum; i++)
{
iChannelNum[i + dwAChanTotalNum] = i + (int)m_struIpParaCfgV40.dwStartDChan;
byStreamType = m_struIpParaCfgV40.struStreamMode[i].byGetStreamType; dwSize = (uint)Marshal.SizeOf(m_struIpParaCfgV40.struStreamMode[i].uGetStream);
switch (byStreamType)
{
//目前NVR仅支持直接从设备取流 NVR supports only the mode: get stream from device directly
case 0:
IntPtr ptrChanInfo = Marshal.AllocHGlobal((Int32)dwSize);
Marshal.StructureToPtr(m_struIpParaCfgV40.struStreamMode[i].uGetStream, ptrChanInfo, false);
m_struChanInfo = (CHCNetSDK.NET_DVR_IPCHANINFO)Marshal.PtrToStructure(ptrChanInfo, typeof(CHCNetSDK.NET_DVR_IPCHANINFO)); //列出IP通道 List the IP channel
ListIPChannel(i + 1, m_struChanInfo.byEnable, m_struChanInfo.byIPID);
iIPDevID[i] = m_struChanInfo.byIPID + m_struChanInfo.byIPIDHigh * 256 - iGroupNo * 64 - 1; Marshal.FreeHGlobal(ptrChanInfo);
break;
case 4:
IntPtr ptrStreamURL = Marshal.AllocHGlobal((Int32)dwSize);
Marshal.StructureToPtr(m_struIpParaCfgV40.struStreamMode[i].uGetStream, ptrStreamURL, false);
m_struStreamURL = (CHCNetSDK.NET_DVR_PU_STREAM_URL)Marshal.PtrToStructure(ptrStreamURL, typeof(CHCNetSDK.NET_DVR_PU_STREAM_URL)); //列出IP通道 List the IP channel
ListIPChannel(i + 1, m_struStreamURL.byEnable, m_struStreamURL.wIPID);
iIPDevID[i] = m_struStreamURL.wIPID - iGroupNo * 64 - 1; Marshal.FreeHGlobal(ptrStreamURL);
break;
case 6:
IntPtr ptrChanInfoV40 = Marshal.AllocHGlobal((Int32)dwSize);
Marshal.StructureToPtr(m_struIpParaCfgV40.struStreamMode[i].uGetStream, ptrChanInfoV40, false);
m_struChanInfoV40 = (CHCNetSDK.NET_DVR_IPCHANINFO_V40)Marshal.PtrToStructure(ptrChanInfoV40, typeof(CHCNetSDK.NET_DVR_IPCHANINFO_V40)); //列出IP通道 List the IP channel
ListIPChannel(i + 1, m_struChanInfoV40.byEnable, m_struChanInfoV40.wIPID);
iIPDevID[i] = m_struChanInfoV40.wIPID - iGroupNo * 64 - 1; Marshal.FreeHGlobal(ptrChanInfoV40);
break;
default:
break;
}
}
}
Marshal.FreeHGlobal(ptrIpParaCfgV40); }
上面展示的是设备注册链接时要申请的变量;接下来开始链接,这里用一个button去实现用户连接的功能:
private void button1_Click(object sender, EventArgs e)
{
if (m_lUserID < 0)
{
string DVRIPAddress = tb_IP.Text; //设备IP地址或者域名 Device IP
Int16 DVRPortNumber = Int16.Parse(tb_Port.Text);//设备服务端口号 Device Port
string DVRUserName = tb_ID.Text;//设备登录用户名 User name to login
string DVRPassword = tb_Pwd.Text;//设备登录密码 Password to login //登录设备 Login the device
m_lUserID = CHCNetSDK.NET_DVR_Login_V30(DVRIPAddress, DVRPortNumber, DVRUserName, DVRPassword, ref DeviceInfo);
if (m_lUserID < 0)
{
iLastErr = CHCNetSDK.NET_DVR_GetLastError();
str = "NET_DVR_Login_V30 failed, error code= " + iLastErr; //登录失败,输出错误号 Failed to login and output the error code
return;
}
else
{
//登录成功
button1.Text = "断开"; dwAChanTotalNum = (uint)DeviceInfo.byChanNum;
dwDChanTotalNum = (uint)DeviceInfo.byIPChanNum + 256 * (uint)DeviceInfo.byHighDChanNum;
if (dwDChanTotalNum > 0)
{
InfoIPChannel();
}
else
{
for (i = 0; i < dwAChanTotalNum; i++)
{
ListAnalogChannel(i + 1, 1);
iChannelNum[i] = i + (int)DeviceInfo.byStartChan;
} //comboBoxView.SelectedItem = 1;
// MessageBox.Show("This device has no IP channel!");
}
} }
else
{
//注销登录 Logout the device
if (m_lRealHandle >= 0)
{
m_lUserID = -1;
button1.Text = "连接相机";
return;
} if (!CHCNetSDK.NET_DVR_Logout(m_lUserID))
{
iLastErr = CHCNetSDK.NET_DVR_GetLastError();
str = "NET_DVR_Logout failed, error code= " + iLastErr;
return;
}
//listViewIPChannel.Items.Clear();//清空通道列表 Clean up the channel list
m_lUserID = -1;
button1.Text = "连接相机";
} if (m_lRealHandle < 0)
{
//lpPreviewInfo.hPlayWnd = RealPlayWnd.Handle;//预览窗口 live view window
lpPreviewInfo.lChannel = iChannelNum[(int)iSelIndex];//预览的设备通道 the device channel number
lpPreviewInfo.dwStreamType = 0;//码流类型:0-主码流,1-子码流,2-码流3,3-码流4,以此类推
lpPreviewInfo.dwLinkMode = 0;//连接方式:0- TCP方式,1- UDP方式,2- 多播方式,3- RTP方式,4-RTP/RTSP,5-RSTP/HTTP
lpPreviewInfo.bBlocked = true; //0- 非阻塞取流,1- 阻塞取流
lpPreviewInfo.dwDisplayBufNum = 15; //播放库显示缓冲区最大帧数 IntPtr pUser = IntPtr.Zero;//用户数据 user data //if (comboBoxView.SelectedIndex == 0)
//{
//打开预览 Start live view
m_lRealHandle = CHCNetSDK.NET_DVR_RealPlay_V40(m_lUserID, ref lpPreviewInfo, null/*RealData*/, pUser);
//}
//else
//{
// lpPreviewInfo.hPlayWnd = IntPtr.Zero;//预览窗口 live view window
// m_ptrRealHandle = RealPlayWnd.Handle;
// RealData = new CHCNetSDK.REALDATACALLBACK(RealDataCallBack);//预览实时流回调函数 real-time stream callback function
// m_lRealHandle = CHCNetSDK.NET_DVR_RealPlay_V40(m_lUserID, ref lpPreviewInfo, RealData, pUser);
//} if (m_lRealHandle < 0)
{
iLastErr = CHCNetSDK.NET_DVR_GetLastError();
str = "NET_DVR_RealPlay_V40 failed, error code= " + iLastErr; //预览失败,输出错误号 failed to start live view, and output the error code.
return;
}
else
{
////预览成功
//DebugInfo("NET_DVR_RealPlay_V40 succ!");
//btnPreview.Text = "Stop View";
MessageBox.Show("连接成功!");
}
}
return;
}
到这里没报错的话就说明连接上了
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#)的更多相关文章
- 通过ISAPI http协议控制海康摄像头
一直用海康的SDK进行摄像头控制,但有时候非常不灵活,必须有X86的主机,在嵌入式上面就不行,通过写一个HTTPCLIENT可以通过ISAPI来控制海康的摄像头. 代码如下:git@github.co ...
- Java 实现 海康摄像头抓拍图像 Windows、Linux
先抱怨一下,打死都想不到,海康的摄像头SDK居然是一个Java类,还有必须的两个jar包(jna.jar,examples.jar).鬼能想得到会这么命名. 下面开始吧. Windows 把从官网下载 ...
- 用libevent写的海康摄像头rtsp客户端
之前一直使用live555作为RTSP的客户端,但其框架臃肿,虽然支持各种格式,但实际中并没有这些需求,关键是其注重于格式的解析,却不注重网络IO,单线程下性能也不高,重新用libevent编写rts ...
- iNeuOS工业互联平台,WEB组态(iNeuView)集成rtmp和websocket视频元件,支持海康、大华等摄像头实时显示视频
目 录 1. 概述... 1 2. 平台演示... 2 3. 硬件摄像头... 2 4. 视频流协议转换管理... 2 5. 组态视频元件 ...
- 海康摄像头配置固定IP
前言 首先要海康设备连接好网线,电脑客户端跟海康设备在同一个局域网络. 1.直接在海康网站下载SADP工具软件,安装SADP工具,如图所示: 2.安装成功后,桌面的出现设备网络搜索, 面板介绍:这里将 ...
- 海康,睿网设备SDK调试
引入 外部dll DllImport [DllImport(@"../bin/HCNetSDK.dll")] 问题1: 找不到模块.... 解决: [DllImport(@&q ...
- 海康SDK编程指南(C#二次开发版本)
海康SDK编程指南 目前使用的海康SDK包括IPC_SDK(硬件设备),Plat_SDK(平台),其中两套SDK都需单独调用海康播放库PlayCtrl.dll来解码视频流,返回视频信息和角度信息.本文 ...
- 海康SDK编程指南
转至心澄欲遣 目前使用的海康SDK包括IPC_SDK(硬件设备),Plat_SDK(平台),其中两套SDK都需单独调用海康播放库PlayCtrl.dll来解码视频流,返回视频信息和角度信息.本文仅对视 ...
- 海康网络摄像机YV12转换为BGR,由opencv Mat显示 (转)
我使用的是海康DS-2CD852MF-E, 200万,网络摄像机,已经比较老了,不过SDK在海康官网下载的,开发流程都差不多. 海康摄像机回调解码后的视频数据格式为YV12,顺便说一下YV12的数据格 ...
随机推荐
- 使用uiautomatorviewer,查看app页面元素,进行元素定位
环境搭建: 安装adt,安装成功后,就可以在adt路径下的tools文件夹中找到uiautomatorviewer.bat 用来做什么? uiautomatorviewer.bat是用来扫描和分析An ...
- golang strings.Split函数
golang strings.Split函数 https://play.studygolang.com/ package main import ( "fmt" "str ...
- HTML5元素
1.1结构元素 HTML5定义了一组新的语义化标签,目前主流浏览器均已支持,语义化标签使用标记元素的内容,虽然可以使用原有标签替换,但是它可以简化HTML页面设计,并且也为搜索引擎在抓取和索引网页的时 ...
- Java NIO Channel 使用
Java NIO 中的 Channel 分类: FileChannel SocketChannel ServerSocketChannel DatagramChannel channel 分类 Fil ...
- CTF-sql-group by报错注入
本文章主要涉及group by报错注入的原理讲解,如有错误,望指出.(附有目录,如需查看请点右下角) 一.下图为本次文章所使用到 user表,该表所在的数据库为 test 二.首先介绍一下本文章所使用 ...
- 🏆【Alibaba中间件技术系列】「RocketMQ技术专题」Broker服务端自动创建topic的原理分析和问题要点指南
前提背景 使用RocketMQ进行发消息时,一般我们是必须要指定topic,此外topic必须要提前建立,但是topic的创建(自动或者手动方式)的设置有一个开关autoCreateTopicEnab ...
- 【笔记】macos上部署thanos_receiver + thanos_query
为了方便起见,在mac笔记本上进行了测试 1.写一个发送数据的客户端 package main import ( "fmt" "io/ioutil" " ...
- js复制标题和链接
问题 常常在写博客和作业时候,需要附上参考链接. 希望可以一键得到标题和链接. 解决方案 普通元素 可以使用findid然后复制 但是标题无法使用 <!DOCTYPE html> < ...
- Shell 脚本循环遍历日志文件中的值进行求和并计算平均值,最大值和最小值
本文为博主原创,转载请注明出处: 最近在进行压测,为了观察并定位服务性能的瓶颈,所以在代码中很多地方加了执行耗时的日志,但这种方式只能观察,却在压测的时候,不太能准确的把握代码中某些方法的性能,所以想 ...
- 外观模式(Facade模式)
外观模式的定义与特点 外观(Facade)模式又叫作门面模式,是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式.该模式对外有一个统一接口,外部应用程序不用关心内部子系 ...