• 海康摄像头二次开发


    硬件介绍

    请添加图片描述

    参考资料

    下载网址
    这个专栏讲的挺不错的
    完整程序代码
    在这里插入图片描述

    在这里插入图片描述

    连接

    在这里插入图片描述

    登录激活,在网页上使用的时候需要下载插件,不然无法实现预览功能。
    在这里插入图片描述
    在这里插入图片描述
    下载玩插件就能显示 能用了

    基础知识

    码流

    1、码流(Data Rate)是指视频文件在单位时间内使用的数据流量,也叫码率,是视频编码中画面质量控制中最重要的部分。同样分辨率下,视频文件的码流越大,压缩比就越小,画面质量就越好。

    2、主码流与子码流的区别

    • 海康威视首家提出了主码流与子码流这样的概念,是为了解决在网络情况不好时为了满足远程预览的流畅性降低码率,而不影响本地录像提出的双码流技术,即一路视频进入NVR(Network Video Recorder即网络硬盘录像机)后,NVR可以编码提供两种码流,主码流和子码流,主码流分辨率高于子码流,主码流用来录像,子码流用来网传。这就叫双码流技术。目的是用于解决监控录像的本地存储和网络传输的图像的质量问题。
    • 主码流一般码流较大,清晰度高,占用的带宽也就高。子码流在主码流的图像环境下降低了图像格式,清晰度较主码流要低,占用带宽小。主码流一般用于存储,子码流用于网传。主码流本地存储,子码流适用于图像在低带宽网络上传输。
    • 总结:主码流图像清晰,所以占用带宽大,因此更适用于保存。而子码流图像不清晰一点,更适用于网络传输。

    代码

    1、适用型号
    在这里插入图片描述

    2、分为三个部分,登录 预览 对讲

    功能实现

    在这里插入图片描述
    云台控制
    在这里插入图片描述

    加载dll

    1、海康提供的设备网络SDK是封装的动态链接库(Windows的dll或者Linux的so),各种开发语言对接SDK,都是通过加载动态库链接,调用动态库中的接口实现功能模块对接,因此,设备网络SDK的对接不区分开发语言,而且对接的流程和对应的接口都是通用的,各种语言调用动态库的方式有所不同。本文重点介绍C#开发语言如何对接设备网络SDK。

    2、使用DllImport方式加载封装好的.dll动态库(DllImport是System.Runtime.InteropServices命名空间下的一个属性类,因此要使用DllImport,必须在HCNetSDK.cs类中在先导入这个类“using System.Runtime.InteropServices;”),从而调用动态库里封装好的方法。我们需要做的只是将dll导入release/debug目录中;因为C/C++的类型与C#的数据类型是不一样的,动态库中的C/C++的数据类型必须转换成C#对应类型;然后声明;然后调用就可以了。

    3、需要注意的是,程序编译环境位数于加载的SDK动态库位数需要保持一致。可以右键项目,在属性–生成–目标平台,选择对应的位数。如果是”Any CPU”则加载的库文件需要和操作系统位数一致(64位操作系统下加载64位库文件,32位操作系统下加载32位库文件),如果是“X86”则只能加载32位的SDK动态库,如果是“X64”则只能加载64位的SDK动态库。

    在这里插入图片描述
    在这里插入图片描述

    下面是直接copy 官方的demo中已经弄好了的

    下载链接,想直接copy进来的 太多了放不下 稍微放一点点吧

    using System;
    using System.Runtime.InteropServices;
    
    namespace LoginTest
    {
        public class HCNetSDK
        {
            #region HCNetSDK.dll function definition
            // function definition
            /* The SDK initialization function */
    
            // 初始化SDK,调用其他SDK函数的前提
            [DllImport(@"HCNetSDK.dll")]
            public static extern bool NET_DVR_Init();
    
            // 启用日志文件写入接口
            [DllImport(@"HCNetSDK.dll")]
            public static extern bool NET_DVR_SetLogToFile(int nLogLevel, IntPtr strLogDir, bool bAutoDel);
    
            // 返回最后操作的错误码
            [DllImport(@"HCNetSDK.dll")]
            public static extern uint NET_DVR_GetLastError();
    
            // 释放SDK资源,在程序结束之前调用
            [DllImport(@"HCNetSDK.dll")]
            public static extern bool NET_DVR_Cleanup();
    
            // 登录接口
            [DllImport(@"HCNetSDK.dll")]
            public static extern int NET_DVR_Login_V40(ref NET_DVR_USER_LOGIN_INFO pLoginInfo, ref NET_DVR_DEVICEINFO_V40 lpDeviceInfo);
    
            // 用户注销
            [DllImport(@"HCNetSDK.dll")]
            public static extern bool NET_DVR_Logout(int lUserID);
    
            // 回调函数声明,登录状态回调函数
            public delegate void LoginResultCallBack(int lUserID, uint dwResult, ref NET_DVR_DEVICEINFO_V30 lpDeviceInfo, IntPtr pUser);
            #endregion
        }
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    #region HCNetSDK.dll structure definition
    
    [StructLayout(LayoutKind.Sequential)]
    public struct NET_DVR_USER_LOGIN_INFO
    {
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = NET_DVR_DEV_ADDRESS_MAX_LEN, ArraySubType = UnmanagedType.I1)]
        public byte[] sDeviceAddress;
        public byte byUseTransport;
        public ushort wPort;
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = NET_DVR_LOGIN_USERNAME_MAX_LEN, ArraySubType = UnmanagedType.I1)]
        public byte[] sUserName;
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = NET_DVR_LOGIN_PASSWD_MAX_LEN, ArraySubType = UnmanagedType.I1)]
        public byte[] sPassword;
        public LoginResultCallBack cbLoginResult;
        public IntPtr pUser;
        public bool bUseAsynLogin;
        public byte byProxyType; //0:不使用代理,1:使用标准代理,2:使用EHome代理
        public byte byUseUTCTime;    //0-不进行转换,默认,1-接口上输入输出全部使用UTC时间,SDK完成UTC时间与设备时区的转换,2-接口上输入输出全部使用平台本地时间,SDK完成平台本地时间与设备时区的转换
        public byte byLoginMode; //0-Private, 1-ISAPI, 2-自适应
        public byte byHttps;    //0-不适用tls,1-使用tls 2-自适应
        public uint iProxyID;    //代理服务器序号,添加代理服务器信息时,相对应的服务器数组下表值
        public byte byVerifyMode;  //认证方式,0-不认证,1-双向认证,2-单向认证;认证仅在使用TLS的时候生效;    
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 119, ArraySubType = UnmanagedType.I1)]
        public byte[] byRes3;
    }
    
    public const int NET_DVR_DEV_ADDRESS_MAX_LEN = 129; //device address max length
    public const int NET_DVR_LOGIN_USERNAME_MAX_LEN = 64;   //login username max length
    public const int NET_DVR_LOGIN_PASSWD_MAX_LEN = 64; //login password max length
    
    #endregion
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    登录

    分为以下几个步骤

    1、在构造函数中,初始化SDK:NET_DVR_Init()

     private bool m_bInitSDK = false;
    
    • 1
            public Form1()
            {
                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, "C:\\SdkLog\\", true);
                }
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2、登录(注册)设备.NET_DVR_Login_V40(ref struLogInfo, ref DeviceInfo);

    • 前面都是登录api中的结构体进行设置
    • 登录有两种模式:同步和异步,同步比较简单,直接调用API就可以了,缺点是需要阻塞界面,用户体验不好;异步,无需阻塞界面,登录状态通过回调函数告知,相对比较麻烦一些详解
            public static  Int32 m_lUserID = -1;//用户ID 登录句柄 登录成功就为非负数 否则为负数
            public CHCNetSDK.NET_DVR_USER_LOGIN_INFO struLogInfo;//登录信息结构体
            CHCNetSDK.LOGINRESULTCALLBACK LoginCallBack = null;
            public CHCNetSDK.NET_DVR_DEVICEINFO_V40 DeviceInfo;
            private uint iLastErr = 0;
            private string str;
            string conState = "登录状态";
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    
            private void uiButton2_Click(object sender, EventArgs e)
            {
                if (m_lUserID < 0)
                {
                    //1、struLogInfo  结构体的创建与赋值
                    struLogInfo = new CHCNetSDK.NET_DVR_USER_LOGIN_INFO();
    
                    //设备IP地址或者域名
                    string nip = "192.168.1.64";
                    byte[] byIP = System.Text.Encoding.Default.GetBytes(nip);
                    struLogInfo.sDeviceAddress = new byte[129];
                    byIP.CopyTo(struLogInfo.sDeviceAddress, 0);
    
                    //设备用户名
                    string nusername = "admin";
                    byte[] byUserName = System.Text.Encoding.Default.GetBytes(nusername);
                    struLogInfo.sUserName = new byte[64];
                    byUserName.CopyTo(struLogInfo.sUserName, 0);
    
                    //设备密码
                    string npassword = "*******";//这里输密码
                    byte[] byPassword = System.Text.Encoding.Default.GetBytes(npassword);
                    struLogInfo.sPassword = new byte[64];
                    byPassword.CopyTo(struLogInfo.sPassword, 0);
    
                    struLogInfo.wPort = ushort.Parse("8000");//设备服务端口号
    
                    if (LoginCallBack == null)
                    {
                        LoginCallBack = new CHCNetSDK.LOGINRESULTCALLBACK(cbLoginCallBack);//注册回调函数                    
                    }
                    struLogInfo.cbLoginResult = LoginCallBack;//注册回调函数
                    struLogInfo.bUseAsynLogin = false; //是否异步登录:0- 否,1- 是 
    
    
                    //2、DeviceInfo: 结构体的创建与赋值
                    DeviceInfo = new CHCNetSDK.NET_DVR_DEVICEINFO_V40();
    
                    //3、登录设备 Login the device
                    //m_lUserID:就是用户ID
                    m_lUserID = CHCNetSDK.NET_DVR_Login_V40(ref struLogInfo, ref DeviceInfo);//NET_DVR_Login_V40用户注册设备
                   
                    
                    if (m_lUserID < 0)
                    {
                        iLastErr = CHCNetSDK.NET_DVR_GetLastError();//获得错误码
                        str = "NET_DVR_Login_V40 failed, error code= " + iLastErr; //登录失败,输出错误号
                        MessageBox.Show(str);
                        return;
                    }
                    else
                    {
                        //登录成功
                        MessageBox.Show("Login Success!");
                        uiLabel1.Text = string.Concat(conState, "成功");
                    }
    
                }
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
            public delegate void UpdateTextStatusCallback(string strLogStatus, IntPtr lpDeviceInfo);
            /**
             * lUserID 
                  [out] 用户ID,NET_DVR_Login_V40的返回值 
                dwResult 
                  [out] 登录状态:0- 异步登录失败,1- 异步登录成功 
                lpDeviceInfo 
                  [out] 设备信息,设备序列号、通道、能力等参数 
                pUser 
                  [out] 用户数据 
             */  
            public void cbLoginCallBack(int lUserID, int dwResult, IntPtr lpDeviceInfo, IntPtr pUser)
            {
                string strLoginCallBack = "登录设备,lUserID:" + lUserID + ",dwResult:" + dwResult;
    
                //异步登录失败
                if (dwResult == 0)
                {
                    uint iErrCode = CHCNetSDK.NET_DVR_GetLastError();
                    strLoginCallBack = strLoginCallBack + ",错误号:" + iErrCode;
                }
    
                //下面代码注释掉也会崩溃
                if (InvokeRequired)
                {
                    object[] paras = new object[2];
                    paras[0] = strLoginCallBack;
                    paras[1] = lpDeviceInfo;
                    uiLabel1.BeginInvoke(new UpdateTextStatusCallback(UpdateClientList), paras);
                }
                else
                {
                    //创建该控件的主线程直接更新信息列表 
                    UpdateClientList(strLoginCallBack, lpDeviceInfo);
                }
    
            }
            public void UpdateClientList(string strLogStatus, IntPtr lpDeviceInfo)
            {
                //列表新增报警信息
                uiLabel1.Text = "登录状态:" + strLogStatus;
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    3、注销 释放资源

                //注销登录 Logout the device
                if (m_lUserID >= 0)
                {
                    CHCNetSDK.NET_DVR_Logout(m_lUserID);
                    m_lUserID = -1;
                }
    
                CHCNetSDK.NET_DVR_Cleanup();//释放SDK资源
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    预览

    登录之后使用
    直接demo和SDK一起看 等需要高端应用的时候再研究 不然直接复制demo的代码就可以正常使用了
    我增加了一段预览后 切到一个预置点,这个点的位置通过云台控制设置(云台设置这里需要点击保存)

            public static Int32 m_lRealHandle = -1;//预览api 句柄 失败就是小于-1
            CHCNetSDK.REALDATACALLBACK RealData = null;
    
            private void uiButton5_Click(object sender, EventArgs e)
            {
                if (m_lUserID < 0)
                {
                    MessageBox.Show("Please login the device firstly");
                    return;
                }
    
                if (m_lRealHandle < 0)
                {
                    CHCNetSDK.NET_DVR_PREVIEWINFO lpPreviewInfo = new CHCNetSDK.NET_DVR_PREVIEWINFO();
                    lpPreviewInfo.hPlayWnd = pictureBox1.Handle;//预览窗口
                    lpPreviewInfo.lChannel = Int16.Parse(textBoxChannel.Text);//预te览的设备通道
                    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 = 1; //播放库播放缓冲区最大缓冲帧数
                    lpPreviewInfo.byProtoType = 0;
                    lpPreviewInfo.byPreviewMode = 0;
    
                    if (textBoxID.Text != "")
                    {
                        lpPreviewInfo.lChannel = -1;
                        byte[] byStreamID = System.Text.Encoding.Default.GetBytes(textBoxID.Text);
                        lpPreviewInfo.byStreamID = new byte[32];
                        byStreamID.CopyTo(lpPreviewInfo.byStreamID, 0);
                    }
    
    
                    if (RealData == null)
                    {
                        RealData = new CHCNetSDK.REALDATACALLBACK(RealDataCallBack);//预览实时流回调函数
                    }
    
                    IntPtr pUser = new IntPtr();//用户数据
    
                    //打开预览 Start live view 
                    m_lRealHandle = CHCNetSDK.NET_DVR_RealPlay_V40(m_lUserID, ref lpPreviewInfo, null/*RealData*/, pUser);
                    if (m_lRealHandle < 0)
                    {
                        iLastErr = CHCNetSDK.NET_DVR_GetLastError();
                        str = "NET_DVR_RealPlay_V40 failed, error code= " + iLastErr; //预览失败,输出错误号
                        MessageBox.Show(str);
                        return;
                    }
                    else
                    {
                        //预览成功
                        uiButton5.Text = "Stop Live View";
                    }
    
                    //调用预设点
                        if (!CHCNetSDK.NET_DVR_PTZPreset_Other(m_lUserID, 1, CHCNetSDK.GOTO_PRESET,ptzC.PresetPoint))
                        {
                            iLastErr = CHCNetSDK.NET_DVR_GetLastError();
                            str = "NET_DVR_PTZPreset_Other failed, error code= " + iLastErr;
                            MessageBox.Show(str);
                            return;
                        }
                        else
                        {
                           // MessageBox.Show("调用成功");
                        }
                        return;
                }
                else
                {
                    //停止预览 Stop live view 
                    if (!CHCNetSDK.NET_DVR_StopRealPlay(m_lRealHandle))
                    {
                        iLastErr = CHCNetSDK.NET_DVR_GetLastError();
                        str = "NET_DVR_StopRealPlay failed, error code= " + iLastErr;
                        MessageBox.Show(str);
                        return;
                    }
                    m_lRealHandle = -1;
                    uiButton5.Text = "Live View";
    
                }
                return;
            }
    
            public void RealDataCallBack(Int32 lRealHandle, UInt32 dwDataType, IntPtr pBuffer, UInt32 dwBufSize, IntPtr pUser)
            {
                if (dwBufSize > 0)
                {
                    byte[] sData = new byte[dwBufSize];
                    Marshal.Copy(pBuffer, sData, 0, (Int32)dwBufSize);//System.Runtime.InteropServices
    
                    string str = "实时流数据.ps";
                    FileStream fs = new FileStream(str, FileMode.Create);
                    int iLen = (int)dwBufSize;
                    // 将字节块写入文件流。
                    fs.Write(sData, 0, iLen);
                    fs.Close();
                }
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100

    语音

    登录之后使用
    直接demo和SDK一起看 等需要高端应用的时候再研究 不然直接复制demo的代码就可以正常使用了

          private bool m_bTalk = false;
            private int lVoiceComHandle = -1;
            //开始语音对讲 Start two-way talk
            CHCNetSDK.VOICEDATACALLBACKV30 VoiceData = new CHCNetSDK.VOICEDATACALLBACKV30(VoiceDataCallBack);//预览实时流回调函数
    
            private void uiButton1_Click(object sender, EventArgs e)
            {
                if (m_bTalk == false)
                {
    
                    lVoiceComHandle = CHCNetSDK.NET_DVR_StartVoiceCom_V30(m_lUserID, 1, true, VoiceData, IntPtr.Zero);
                    //bNeedCBNoEncData [in]需要回调的语音数据类型:0- 编码后的语音数据,1- 编码前的PCM原始数据
    
                    GC.KeepAlive(VoiceData);
                    GC.KeepAlive(lVoiceComHandle);
    
                    if (lVoiceComHandle < 0)
                    {
                        iLastErr = CHCNetSDK.NET_DVR_GetLastError();
                        str = "NET_DVR_StartVoiceCom_V30 failed, error code= " + iLastErr;
                        MessageBox.Show(str);
                        return;
                    }
                    else
                    {
                        //uiButton1.FillColor = Color.FromArgb(255, 140, 222, 217);
                        //uiButton1.FillPressColor = Color.FromArgb(255, 140, 222, 217);
                        //uiButton1.FillSelectedColor = Color.FromArgb(255, 140, 222, 217);
                        //uiButton1.Text = "停止对讲";
                        uiButton1.BackgroundImage = Image.FromFile(path + "\\img\\分组 2.png");
                        m_bTalk = true;
                    }
                }
                else
                {
                    GC.KeepAlive(VoiceData);
                    GC.KeepAlive(lVoiceComHandle);
    
                    //停止语音对讲 Stop two-way talk
                    if (!CHCNetSDK.NET_DVR_StopVoiceCom(lVoiceComHandle))
                    {
                        iLastErr = CHCNetSDK.NET_DVR_GetLastError();
                        str = "NET_DVR_StopVoiceCom failed, error code= " + iLastErr;
                        MessageBox.Show(str);
                        return;
                    }
                    else
                    {
                        //uiButton1.FillColor = Color.FromArgb(255, 5, 28, 62);
                        //uiButton1.FillPressColor = Color.FromArgb(255, 5, 28, 62);
                        //uiButton1.FillSelectedColor = Color.FromArgb(255, 5, 28, 62);
                        //uiButton1.Text = "开始对讲";
                        uiButton1.BackgroundImage = Image.FromFile(path + "\\img\\确定 copy_1.png");
                        m_bTalk = false;
                    }
                }
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    回调函数

          public static void VoiceDataCallBack(int lVoiceComHandle, IntPtr pRecvDataBuffer, uint dwBufSize, byte byAudioFlag, System.IntPtr pUser)
            {
                byte[] sString = new byte[dwBufSize];
                Marshal.Copy(pRecvDataBuffer, sString, 0, (Int32)dwBufSize);
                
                if (byAudioFlag == 0)
                {
                    //将缓冲区里的音频数据写入文件 save the data into a file
                    string str = "PC采集音频文件.pcm";
                    FileStream fs = new FileStream(str, FileMode.Create);
                    int iLen = (int)dwBufSize;
                    fs.Write(sString, 0, iLen);
                    fs.Close();
                }
                if (byAudioFlag == 1)
                {
                    //将缓冲区里的音频数据写入文件 save the data into a file
                    string str = "设备音频文件.pcm";
                    FileStream fs = new FileStream(str, FileMode.Create);
                    int iLen = (int)dwBufSize;
                    //MessageBox.Show("1");
                    fs.Write(sString, 0, iLen);
                    fs.Close();
                }
             
    
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    云台控制

    控制函数再mouse up和down中。保存就是保存当前设置位置到某一个预置点中。在点击
    在这里插入图片描述

            private void UpPtz_MouseDown(object sender, MouseEventArgs e)
            {
                if (Form1.m_lUserID >= 0)
                {
                    if (Form1.liveIndex)
                    {
                        //带速度的云台控制操作(需先启动图象预览)
                        CHCNetSDK.NET_DVR_PTZControlWithSpeed(Form1.m_lRealHandle, CHCNetSDK.TILT_UP, 0, (uint)uiComboBox1.SelectedIndex + 1);
                    }
                    else
                    {
                        //带速度的云台控制操作(不用启动图象预览)。
                        CHCNetSDK.NET_DVR_PTZControlWithSpeed_Other(Form1.m_lUserID, 1, CHCNetSDK.TILT_UP, 0, (uint)uiComboBox1.SelectedIndex + 1);
                    }
                }
                else
                {
                    MessageBox.Show("请先登录");
                }
            }
    
            private void UpPtz_MouseUp(object sender, MouseEventArgs e)
            {
                if (Form1.m_lUserID >= 0)
                {
                    if (Form1.liveIndex)
                    {
                        //带速度的云台控制操作(需先启动图象预览)
                        CHCNetSDK.NET_DVR_PTZControlWithSpeed(Form1.m_lRealHandle, CHCNetSDK.TILT_UP, 1, (uint)uiComboBox1.SelectedIndex + 1);
                    }
                    else
                    {
                        //带速度的云台控制操作(不用启动图象预览)。
                        CHCNetSDK.NET_DVR_PTZControlWithSpeed_Other(Form1.m_lUserID, 1, CHCNetSDK.TILT_UP, 1, (uint)uiComboBox1.SelectedIndex + 1);
                    }
                }
                else
                {
                    MessageBox.Show("请先登录");
                }
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
            private void DownPtz_MouseDown(object sender, MouseEventArgs e)
            {
                if (Form1.m_lUserID >= 0)
                {
                    if (Form1.liveIndex)
                    {
                        //带速度的云台控制操作(需先启动图象预览)
                        CHCNetSDK.NET_DVR_PTZControlWithSpeed(Form1.m_lRealHandle, CHCNetSDK.TILT_DOWN, 0, (uint)uiComboBox1.SelectedIndex + 1);
                    }
                    else
                    {
                        //带速度的云台控制操作(不用启动图象预览)。
                        CHCNetSDK.NET_DVR_PTZControlWithSpeed_Other(Form1.m_lUserID, 1, CHCNetSDK.TILT_DOWN, 0, (uint)uiComboBox1.SelectedIndex + 1);
                    }
                }
                else
                {
                    MessageBox.Show("请先登录");
                }
            }
    
            private void DownPtz_MouseUp(object sender, MouseEventArgs e)
            {
                if (Form1.m_lUserID >= 0)
                {
                    if (Form1.liveIndex)
                    {
                        //带速度的云台控制操作(需先启动图象预览)
                        CHCNetSDK.NET_DVR_PTZControlWithSpeed(Form1.m_lRealHandle, CHCNetSDK.TILT_DOWN, 1, (uint)uiComboBox1.SelectedIndex + 1);
                    }
                    else
                    {
                        //带速度的云台控制操作(不用启动图象预览)。
                        CHCNetSDK.NET_DVR_PTZControlWithSpeed_Other(Form1.m_lUserID, 1, CHCNetSDK.TILT_DOWN, 1, (uint)uiComboBox1.SelectedIndex + 1);
                    }
                }
                else
                {
                    //MessageBox.Show("请先登录");
                }
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
            private void LeftPtz_MouseDown(object sender, MouseEventArgs e)
            {
                if (Form1.m_lUserID >= 0)
                {
                    if (Form1.liveIndex)
                    {
                        //带速度的云台控制操作(需先启动图象预览)
                        CHCNetSDK.NET_DVR_PTZControlWithSpeed(Form1.m_lRealHandle, CHCNetSDK.PAN_LEFT, 0, (uint)uiComboBox1.SelectedIndex + 1);
                    }
                    else
                    {
                        //带速度的云台控制操作(不用启动图象预览)。
                        CHCNetSDK.NET_DVR_PTZControlWithSpeed_Other(Form1.m_lUserID, 1, CHCNetSDK.PAN_LEFT, 0, (uint)uiComboBox1.SelectedIndex + 1);
                    }
                }
                else
                {
                    MessageBox.Show("请先登录");
                }
            }
    
            private void LeftPtz_MouseUp(object sender, MouseEventArgs e)
            {
                if (Form1.m_lUserID >= 0)
                {
                    if (Form1.liveIndex)
                    {
                        //带速度的云台控制操作(需先启动图象预览)
                        CHCNetSDK.NET_DVR_PTZControlWithSpeed(Form1.m_lRealHandle, CHCNetSDK.PAN_LEFT, 1, (uint)uiComboBox1.SelectedIndex + 1);
                    }
                    else
                    {
                        //带速度的云台控制操作(不用启动图象预览)。
                        CHCNetSDK.NET_DVR_PTZControlWithSpeed_Other(Form1.m_lUserID, 1, CHCNetSDK.PAN_LEFT, 1, (uint)uiComboBox1.SelectedIndex + 1);
                    }
                }
                else
                {
                    //MessageBox.Show("请先登录");
                }
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
            private void RightPtz_MouseDown(object sender, MouseEventArgs e)
            {
                if (Form1.m_lUserID >= 0)
                {
                    if (Form1.liveIndex)
                    {
                        //带速度的云台控制操作(需先启动图象预览)
                        CHCNetSDK.NET_DVR_PTZControlWithSpeed(Form1.m_lRealHandle, CHCNetSDK.PAN_RIGHT, 0, (uint)uiComboBox1.SelectedIndex + 1);
                    }
                    else
                    {
                        //带速度的云台控制操作(不用启动图象预览)。
                        CHCNetSDK.NET_DVR_PTZControlWithSpeed_Other(Form1.m_lUserID, 1, CHCNetSDK.PAN_RIGHT, 0, (uint)uiComboBox1.SelectedIndex + 1);
                    }
                }
                else
                {
                    MessageBox.Show("请先登录");
                }
            }
    
            private void RightPtz_MouseUp(object sender, MouseEventArgs e)
            {
                if (Form1.m_lUserID >= 0)
                {
                    if (Form1.liveIndex)
                    {
                        //带速度的云台控制操作(需先启动图象预览)
                        CHCNetSDK.NET_DVR_PTZControlWithSpeed(Form1.m_lRealHandle, CHCNetSDK.PAN_RIGHT, 1, (uint)uiComboBox1.SelectedIndex + 1);
                    }
                    else
                    {
                        //带速度的云台控制操作(不用启动图象预览)。
                        CHCNetSDK.NET_DVR_PTZControlWithSpeed_Other(Form1.m_lUserID, 1, CHCNetSDK.PAN_RIGHT, 1, (uint)uiComboBox1.SelectedIndex + 1);
                    }
                }
                else
                {
                    //MessageBox.Show("请先登录");
                }
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    保存

            private uint iLastErr = 0;
            string str="";
            public static UInt32 PresetPoint = 2;
            private void uiButton1_Click(object sender, EventArgs e)
            {
                if (Form1.m_lUserID >= 0)
                {
                    DialogResult dr;
                    dr = MessageBox.Show("确认将当前点设置为预置点", "设置", MessageBoxButtons.YesNo,
                             MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);
                    if (dr == DialogResult.Yes)
                    {
    
                        if (!CHCNetSDK.NET_DVR_PTZPreset_Other(Form1.m_lUserID, 1, CHCNetSDK.SET_PRESET, PresetPoint))
                        {
                            iLastErr = CHCNetSDK.NET_DVR_GetLastError();
                            str = "NET_DVR_PTZPreset_Other failed, error code= " + iLastErr;
                            MessageBox.Show(str);
                            return;
                        }
                        else
                        {
                            MessageBox.Show("设置成功");
                        }
                        return;
                    }
                    else return;
                }
                else
                {
                    //MessageBox.Show("请先登录");
                }
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    镜像

    可实现上下左右中心的画面切换。

    • 直接在SDK里面搜索镜像,看到包含这个的结构体,和更改结构体的函数。
    • 首先通过NET_DVR_GetDVRConfig获取配置信息,在他传过来的结构体的基础上,进行镜像的修改
    • 一系列结构体的操作。首先申请一段指针内存,将传入的数据被指针指向,然后将指针转成结构体,再修改结构体的值,最后将结构体转换成指针,然后发送出去。参考
    • NET_DVR_SetDVRConfig将修改后的结构体发送出去
            //当您使用 New 操作符创建一个结构对象时,会调用适当的构造函数来创建结构。与类不同,结构可以不使用 New 操作符即可被实例化。
            //如果不使用 New 操作符,只有在所有的字段都被初始化之后,字段才被赋值,对象才被使用。
            public static   CHCNetSDK.NET_DVR_CAMERAPARAMCFG_EX VideoConf=new CHCNetSDK.NET_DVR_CAMERAPARAMCFG_EX();      
            private void uiButton6_Click_1(object sender, EventArgs e)
            {
                try
                {
                    uint lpBytesReturned = 0;
                    //申请指针内存
                    IntPtr iptr = Marshal.AllocHGlobal(Marshal.SizeOf(VideoConf));
                    //获取设备的配置信息。
                    NET_DVR_GetDVRConfig(m_lUserID, 3368, 1, iptr, (uint)Marshal.SizeOf(VideoConf), ref lpBytesReturned);
                    //将指针转换成结构体
                    CHCNetSDK.NET_DVR_CAMERAPARAMCFG_EX entries = (CHCNetSDK.NET_DVR_CAMERAPARAMCFG_EX)Marshal.PtrToStructure(iptr, typeof(CHCNetSDK.NET_DVR_CAMERAPARAMCFG_EX));
                    /* 镜像:0 off,1- leftright,2- updown,3-center */
                    if (uiComboBox2.SelectedItem.ToString()=="上下")
                    {
                        entries.byMirror =2;
                    }
                    else if (uiComboBox2.SelectedItem.ToString() == "左右")
                    {
                        entries.byMirror = 1;
                    }
                    else if (uiComboBox2.SelectedItem.ToString() == "中心")
                    {
                        entries.byMirror = 3;
                    }
                    else if (uiComboBox2.SelectedItem.ToString() == "关闭")
                    {
                        entries.byMirror = 0;
                    }
                    Marshal.StructureToPtr(entries, iptr, true);
                    NET_DVR_SetDVRConfig(m_lUserID, 3369, 1, iptr, (uint)Marshal.SizeOf(VideoConf));
                }
                catch (Exception)
                {
                    throw;
                }
    
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    在这里插入图片描述

    错误码

    CHCNetSDK.NET_DVR_GetLastError();
    
    • 1

    返回值为错误码。错误码主要分为网络通讯库、RTSP通讯库、软硬解库、语音对讲库等错误码,详见下表。他有两百多个 详细见 设备网络SDK使用手册
    在这里插入图片描述
    在这里插入图片描述

    出现的问题

    回调函数导致崩溃

    反复点击语音按钮后出现奔溃,加一行代码就可以了,大致的原因是:c#把回调函数资源回收了,导致api收到事件的时候执行回调出错。

     GC.KeepAlive(VoiceData);
      GC.KeepAlive(lVoiceComHandle);//可能只需要其中的一句 我加了两句
    
    • 1
    • 2

    请添加图片描述
    解决方案详解
    解决方案对口

  • 相关阅读:
    macOS:苹果公司创造的传奇
    如何使用SVN或者Git回滚代码,你必须知道的三种场景
    虚幻阴影整理
    老徐和阿珍的故事:Runnable和Callable有什么不同?
    腾讯广告RACE曝光归因模型
    ElasticSearch搜索引擎:常用的存储mapping配置项 与 doc_values详细介绍
    C++文件服务器项目—项目总结与反向代理—7
    轻量级简约仪表板Dasherr
    spring 事物源码阅读之事务与持久化操作的结合
    经典面试题:为什么 ConcurrentHashMap 的读操作不需要加锁?
  • 原文地址:https://blog.csdn.net/chengcao123/article/details/126711505