海康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);//示例

雲台控制指令如圖:

 

大家有需要可以試一下,練練手!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM