zoukankan      html  css  js  c++  java
  • C# 视频监控系列(3):客户端——连接服务器并预览

    前言

         近一个星期在写服务器端,一直没有成功,就没有继续往下写文章,可喜的是这一局面在今天下午得到改变(客户端已经能够连接我自己写的服务器端了!),顺便说下客户端大概2-3篇文章,接下来就会写关于服务器的文章了,感谢关注,也希望能帮助得到你: )

    推荐文章

         1.     C# 与 C++ 数据类型对照 ,极其推荐!!调用VC++的dll最主要的问题之一就是数据类型对应了!!

         2.     压缩卡及硬盘录像机常见故障集锦,里面有很多关于视频方面的知识。

         3.     大城小格 ,他的博客上有系列文章,虽然简短,仍有很多帮助!

         4.     杭州海康威视数字技术有限公司-疑难解答|常见问题|FAQ

    注意

         本系列文章限于学习交流,注重过程,由于涉及公司,所以不提供源代码下载,非常抱歉!!但是请大家放心,核心、实现以及其他能够贴出来的代码我都会贴出来,并且争取尽所能的回答评论里的每一个问题,感谢大家关注,欢迎交流 :)

    系列

         1.     C# 视频监控系列(1):准备

         2.     C# 视频监控系列(2):客户端——封装API

         3.     C# 视频监控系列(3):客户端——连接服务器

    正文

         1.     将以下四个dll拷贝到system32目录下,这几个文件均在根目录的Bin目录下

                   DS40xxSDK.dll

                   hikclient.dll

                   HikPlayM4.dll

                   HikServer.dll

         2.     先用自带的客户端Net Client Demo(Soft Decdoe)运行下确认没有问题再根据VC++客户端的例子写对应的C#代码。

         3.     最好装一个Microsoft Visual C++ 6.0,这样能把VC++的例子跑起来并调试。注意他是Win32 Release的,需要切换至Win32 Debug模式才能断点调试!!

         4.     打开API文档Hikvision 板卡网络开发包编程手册V4.7,在Doc目录下。

         5.     代码分析和编写对应的C#代码

              5.1     第二章编程说明中第六条我们可以看到API依次调用的顺序,可以根据函数名直接在代码中搜索调用顺序,不难发现,在HKVisionDlg.cppOnInitDialog方法能看到如下两行代码:

        MP4_ClientSetNetPort(5050,6050);

        MP4_ClientStartup(WM_MYCOMMAND,
    this->m_hWnd);

              很明显这是调用了API,其他代码就不用管了,那么我把这代码翻译到C# WinForm的Form1_Load事件里面,并且也这样调用API(封装好的SDK请看上篇文章):

                PcHikClient.MP4_ClientSetNetPort(50506050);
                PcHikClient.MP4_ClientStartup(PcHikClient.WM_USER 
    + 1this.Handle);

              5.2     根据界面上Start按钮事件能找到关键的连接上服务器,如下:

        if (m_showmode == 0)
        {
            MP4_ClientSetShowMode(NORMALMODE,
    0);
        }
        
    else
        {
            MP4_ClientSetShowMode(OVERLAYMODE,COLORREF(
    0xff00ff));
        }

        nn1
    =nn2=nn3=nn4 = -1;

        
    int itemp = m_shownum;
        
    char ips[256];
        
        sprintf(ips,
    "%s",m_ipadd);

        
        hWnd5 
    = m_video5.GetSafeHwnd();//
        aa5.m_bRemoteChannel = 0;
        
    switch(m_linktype)
        {
        
    case 0:
            aa5.m_bSendMode 
    = TCPMODE;
            
    break;
        
    case 1:
            aa5.m_bSendMode 
    = UDPMODE;
            
    break;
        
    case 2:
            aa5.m_bSendMode 
    = MULTIMODE;
            
    break;
        
    case 3:
            aa5.m_bSendMode 
    = DIALING;
            
    break;
        
    case 4:
            aa5.m_bSendMode 
    = AUDIODETACH;
            
    break;
        
    default:
            aa5.m_bSendMode 
    = TCPMODE;
            
    break;
        }

        aa5.m_sIPAddress 
    = ips;
        
    //2003.12.2
        
    //如果想只录像,而不进行解码,可以将m_hShowVideo设置成NULL
        
    //If you just want to record without decode on client side,
        
    //please set m_hShowVideo as NULL
    #if defined RECORD_ONLY
        aa5.m_hShowVideo 
    = NULL;
    #else
        aa5.m_hShowVideo 
    = hWnd5;
    #endif

        
    // add 2003.12.2
        
    //m_nImgFormat 指明想要获取的图像格式
        
    //依赖服务器端的设置。如果不设置,获取的是服务器的缺省格式
        
    //m_nImgFormat indicates the picture format you get on the client side,
        
    //It depends on the setting of Server side.
        aa5.m_nImgFormat = 0;    // request CIF format
    //    aa5.m_nImgFormat = 1;    // request QCIF format

        aa5.m_sUserName 
    = "123";
        aa5.m_sUserPassword
    ="w";
        aa5.m_bUserCheck 
    = TRUE;
        
        MP4_ClientSetTTL(
    64);
        nn1 
    = MP4_ClientStart(&aa5,ReadDataCallBack);
        
    if (nn1 == -1)
        {
            MessageBox(
    "error");
            
    return;
        }
        
    //
        BOOL breturn;
        breturn 
    = MP4_ClientRigisterDrawFun(nn1,DrawFun,0);
        
    switch(m_delaytype)
        {
        
    case 0:
            MP4_ClientSetBufferNum(nn1,
    40);
            MP4_ClientSetPlayDelay(nn1,
    580);
            
    break;
        
    case 1:
            MP4_ClientSetBufferNum(nn1,
    15);
            MP4_ClientSetPlayDelay(nn1,
    40);
            
    break;
        
    case 2:
            MP4_ClientSetBufferNum(nn1,
    15);
            MP4_ClientSetPlayDelay(nn1,
    0);
            
    break;
        
    case 3:
            MP4_ClientSetBufferNum(nn1,
    0);
            MP4_ClientSetPlayDelay(nn1,
    0);
            
    break;
        }


    //    MP4_ClientThrowBFrame(nn1,m_bframenum);
        MP4_ClientSetCapPicCallBack(nn1,CapPicFun);

              有VC++代码可以看得出来接下来代码都和这差不多,应该就是初始化显示四个窗口的代码了,那我们就不需要把这个方法里面的代码全部翻译了,只需要达到连接一个视频窗口的目的就可以了,翻译的过程中可以自己先临时设置一些变量来让代码跑起来,翻译过程中每次都执行到MP4_ClientRigisterDrawFun方法的时候就报错了,但是画面确已经出来了,所有我就从这里截断了,先达到目的再说,请看翻译对象的C#代码:

    int cs;

            
    private void button1_Click(object sender, EventArgs e)
            {
                CLIENT_VIDEOINFO cVideo 
    = new CLIENT_VIDEOINFO();
                
    //对应服务端通道号
                cVideo.m_bRemoteChannel = (byte)0;
                
    //网络连接模式
                cVideo.m_bSendMode = (byte)SEND_MODE.TCPMODE;
                
    //服务端IP地址
                cVideo.m_sIPAddress = "192.168.0.188";
                
    //显示区域
                cVideo.m_hShowVideo = pVideo.Handle;//(IntPtr)null;
                
    //图像格式
                cVideo.m_nImgFormat = (byte)0;
                
    //用户名
                cVideo.m_sUserName = "123";
                
    //密码
                cVideo.m_sUserPassword = "w";
                
    //是否需要发生密码
                cVideo.m_bUserCheck = true;

                
    //设置多播的TTL参数
                PcHikClient.MP4_ClientSetTTL((char)64);
                
    //启动客户端
                cs = PcHikClient.MP4_ClientStart(ref cVideo, new ReadDataCallBack(MyRealDataCallBack1));
            }

            
    private void MyRealDataCallBack1(ulong port, [MarshalAs(UnmanagedType.LPArray)] byte[] pBuffer, ulong pSize)
            {
                MessageBox.Show(pBuffer.Length.ToString());
            }

              需要注意的是,VC++里面的指针类型,如HWND一般可以对应C#里面的IntPtr数据类型,ReadDataCallBack是回调函数,但是没有执行,不过至此画面已经能够显示出来!!

    那么接下来做画面切割,右键事件什么的都只需要你WinForm的开发经验了,我是用的四个面板(Panel)切换隐藏显示的;pVideo是Panel控件;用户名和密码随便设置也能连得上。

              5.3     关闭连接

                   同样找到VC++代码:

        if (nn1 >= 0)
        {
            MP4_ClientStopCapture(nn1);
            MP4_ClientStop(nn1);
        }

                   对应C#代码:

            private void Close()
            {
                PcHikClient.MP4_ClientStopCapture(cs);
                PcHikClient.MP4_ClientStop(cs);
                pVideo.Invalidate(
    true);
            }

                   需要注意的是这个cs变量,在连接的时候MP4_ClientStart返回值,需要拿全局变量保存起来,以便这里关闭的时候需要,从API文章里面我们也能看到这样的说明。这段代码最好在窗体关闭的时候也加上!!

    注意

         摘抄:

    DS400xM/DS400xH卡在客户端机器运行的要求     主要是针对运行客户端程序的计算机显卡有要求,需支持Overlay功能,目前主流的显卡nvidia,ati,Intel845GL集成的系列都支持Overlay功能。

         在PIII 833的计算机上,可以比较流畅的软解码4路普通的实时图象;在PIV 2G的计算机上,可以比较流畅的软解码8-9路普通的实时图象;如果用我们公司的硬解码卡,只要显卡支持Overlay功能,就可以支持最多达24路的实时图象,并且支持VideoOut功能,可以上电视墙。

    结束

         如果本文能带你实现预览的功能,将使你信心百倍,效果才是最有说服力的,并祝你好运: )

  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    网上怎么赚钱?如何利用CPA赚钱?
    在农村养殖什么赚钱?要做好哪些预防工作?
    计算机组成的基本硬件设备
    JAVA回溯法求0-1背包
    TensorFlow学习笔记之批归一化:tf.layers.batch_normalization()函数
    数据库连接池的大小值设定,不能随意设置太大的值
    N皇后问题
    19个强大、有趣、又好玩的 Linux 命令!
    JAVA马的遍历
  • 原文地址:https://www.cnblogs.com/over140/p/1396571.html
Copyright © 2011-2022 走看看