zoukankan      html  css  js  c++  java
  • 大华解码器二次开发/C#调用C++DLL

    先说一下大华解码器的思路,和天地伟业的解码器思路不一样。天地伟业讲究的是一个物理通道对应一块屏幕,至始至终都是都物理通道的操作,优点是简单明了通俗易懂不花里胡哨。

    大华讲究的是开始就把物理通道进行融合,结果就是出来的融合屏必是少于或等于物理屏总数,那么后来的上屏操作都是依托于这个融合屏,融合屏是从物理通道总数开始计起。

    开始:首先把大华写的封装类库(NetSDKCS)添加到项目中。

     1.项目所需的几个参数

    private IntPtr m_LoginHandle = IntPtr.Zero;
    
    private NET_DEVICEINFO_Ex m_DeviceInfo;
    
    private readonly fDisConnectCallBack m_DisConnectHandle;
    
    private string sDeviceIP = "192.168.1.109";
    private ushort wDevicePort = 37777;
    private string sUserName = "admin";
    private string sPassword = "admin";

    2.SDK的初始化

    private void DisConnectCallBack(IntPtr lLoginID, IntPtr pchDVRIP, int nDVRPort, IntPtr dwUser)
    {
         Console.WriteLine(Marshal.PtrToStringAnsi(pchDVRIP) + " disConnect");
    }
    m_DisConnectHandle = new fDisConnectCallBack(DisConnectCallBack);
    NETClient.Init(m_DisConnectHandle, IntPtr.Zero, null);

    3.登录解码器

    m_LoginHandle = NETClient.Login(sDeviceIP, wDevicePort, sUserName, sPassword, EM_LOGIN_SPAC_CAP_TYPE.TCP, IntPtr.Zero, ref m_DeviceInfo);

    4.获取解码器融合通道的窗口信息

    public bool GetSplitWindowsInfo(int nChannel)
    {
    bool bRet = false; NET_SPLIT_CAPS stuCap = new NET_SPLIT_CAPS(); stuCap.dwSize = (uint)Marshal.SizeOf(stuCap); try { bRet = NETClient.GetSplitCaps(m_LoginHandle, nChannel, ref stuCap, 3000); } catch (NETClientExcetion nex) { Console.WriteLine("Failed to get split caps. " + nex.Message); return false; } for (int i = 0; i < stuCap.emSplitMode.Length; i++) { if (stuCap.emSplitMode[i] == EM_SPLIT_MODE.SPLIT_FREE) { NET_IN_SPLIT_GET_WINDOWS stuInGetWhn = new NET_IN_SPLIT_GET_WINDOWS(); stuInGetWhn.nChannel = nChannel; stuInGetWhn.dwSize = (uint)Marshal.SizeOf(stuInGetWhn); NET_OUT_SPLIT_GET_WINDOWS stuOutGetWhn = new NET_OUT_SPLIT_GET_WINDOWS(); stuOutGetWhn.dwSize = (uint)Marshal.SizeOf(stuOutGetWhn); NET_BLOCK_COLLECTION stuBlockColltion = new NET_BLOCK_COLLECTION(); stuBlockColltion.dwSize = (uint)Marshal.SizeOf(stuBlockColltion); object obj = stuBlockColltion; InitStruct(ref obj); stuBlockColltion = (NET_BLOCK_COLLECTION)obj; NET_WINDOW_COLLECTION [] stuWindowColltion = new NET_WINDOW_COLLECTION[128]; for (int x = 0; x < stuWindowColltion.Length; x++) { stuWindowColltion[x].dwSize = (uint)Marshal.SizeOf(stuWindowColltion[x]); } stuBlockColltion.stuWnds = stuWindowColltion; stuOutGetWhn.stuWindows = stuBlockColltion; bRet = NETClient.GetSplitWindowsInfo(m_LoginHandle, ref stuInGetWhn, ref stuOutGetWhn, 3000); for(int x = 0;x < stuOutGetWhn.stuWindows.stuWnds.Length;x ++) { Console.WriteLine("nWindowID:" + stuOutGetWhn.stuWindows.stuWnds[x].nWindowID + "Top:"+stuOutGetWhn.stuWindows.stuWnds[x].stuRect.nTop.ToString()+ "Left:" + stuOutGetWhn.stuWindows.stuWnds[x].stuRect.nLeft.ToString()+ "Right:" + stuOutGetWhn.stuWindows.stuWnds[x].stuRect.nRight.ToString()+ "Bottom:" + stuOutGetWhn.stuWindows.stuWnds[x].stuRect.nBottom.ToString()); } } } return bRet; }

    5.获取融合屏通道信息,必须在开窗之前执行此操作

    public enum emVideoOutType
    {
         ALL = 1,  //物理屏和融合屏
         COMP = 2, //融合屏
         PHY = 3,  //物理屏
    }
    private void InitStruct(ref object stu)
    {
         IntPtr p_stu = IntPtr.Zero;
         Type type = stu.GetType();
         try
         {
              p_stu = Marshal.AllocHGlobal(Marshal.SizeOf(type));
              Marshal.StructureToPtr(stu, p_stu, true);
              stu = Marshal.PtrToStructure(p_stu, type);
         }
         finally
         {
              Marshal.FreeHGlobal(p_stu);
         }
    }
    public bool GetVideoOutChannelInfo()
    {
        bool bRet = false;
        int nComposite = 30; //拼接屏数量
        NET_COMPOSITE_CHANNEL stComChan = new NET_COMPOSITE_CHANNEL();
        object obj = stComChan;
        InitStruct(ref obj);
        stComChan = (NET_COMPOSITE_CHANNEL)obj;
        stComChan.dwSize = (uint)Marshal.SizeOf(stComChan.GetType());
        object[] oComChans = new object[nComposite];
        for (int i = 0; i < nComposite; i++)
        {
           oComChans[i] = stComChan;
        }
        try
        {
            bRet = NETClient.QueryDevState(m_LoginHandle, (int)NETClient.NET_DEVSTATE_COMPOSITE_CHN, ref oComChans, typeof(NET_COMPOSITE_CHANNEL), 3000);
            if (bRet)
            {
                for (int i = 0; i < oComChans.Length; i++)
                {
                    stComChan = (NET_COMPOSITE_CHANNEL)oComChans[i];
                    Console.WriteLine("融合屏: {0}", i);
                    Console.WriteLine("name:{0}", stComChan.szMonitorWallName);
                    Console.WriteLine("融合屏ID: {0}", stComChan.szCompositeID);
                    Console.WriteLine("融合屏通道号: {0}", stComChan.nVirtualChannel);
                }
            }
        }
        catch (NETClientExcetion nex)
        {
            Console.WriteLine(nex.Message);
            return false;
        }
        return bRet;      
    }

    5.自由开窗,来给视频上墙,返回开窗ID,此ID用来视频上墙

    public int ClientSetFreeWindows(int nChannel, int nLeft ,int nTop, int nRight, int nBottom)
    {
        if (!GetVideoOutChannelInfo())//打印下当前融合屏情况
        {
            Console.WriteLine("Failed to get channels info;");
        } 
        NET_IN_SPLIT_OPEN_WINDOW stOpenWindowIn = new NET_IN_SPLIT_OPEN_WINDOW();
        stOpenWindowIn.dwSize = (uint)Marshal.SizeOf(stOpenWindowIn.GetType());
        stOpenWindowIn.nChannel = nChannel;
        stOpenWindowIn.stuRect.nLeft = nLeft;
        stOpenWindowIn.stuRect.nTop = nTop;
        stOpenWindowIn.stuRect.nRight = nRight; 
        stOpenWindowIn.stuRect.nBottom = nBottom;  
        NET_OUT_SPLIT_OPEN_WINDOW stOpenWindowOut = new NET_OUT_SPLIT_OPEN_WINDOW();
        stOpenWindowOut.dwSize = (uint)Marshal.SizeOf(stOpenWindowOut.GetType());
        NET_SPLIT_MODE_INFO stSplitMode = new NET_SPLIT_MODE_INFO();
        stSplitMode.dwSize = (uint)Marshal.SizeOf(stSplitMode.GetType());
        stSplitMode.emSplitMode = EM_SPLIT_MODE.SPLIT_FREE;
        try
        {
            NETClient.SetSplitMode(m_LoginHandle, stOpenWindowIn.nChannel, ref stSplitMode, 3000);//自由分割
            NETClient.OpenSplitWindow(m_LoginHandle, ref stOpenWindowIn, ref stOpenWindowOut, 3000); //开窗
        }
        catch (NETClientExcetion nex)
        {
            Console.WriteLine("Failed to open split window, " + nex.Message);
        }
        return (int)stOpenWindowOut.nWindowID; 
    }

    6.拉流模式,视频上墙

    public bool ClientRealPlay(int nOutChannel,int nWindow,string szIp,string szUserEx,string szPwdEx)
    {
        bool bRet = false;
        int nSrcCount = 1;      //视频源个数 
        NET_SPLIT_SOURCE stSplitSource = new NET_SPLIT_SOURCE();
        stSplitSource.dwSize = (uint)Marshal.SizeOf(stSplitSource);
        stSplitSource.bEnable = true;
        stSplitSource.szIp = szIp; 
        stSplitSource.szUserEx = szUserEx;
        stSplitSource.szPwdEx = szPwdEx;
        stSplitSource.nPort = 37777;
        stSplitSource.nChannelID = 0;   
        stSplitSource.nStreamType = 0;  //主码流
        stSplitSource.nVideoChannel = 1;//视频源设备通道总数,在登陆视频源的时候可以获取到。对于IPC设备,视频通道数是1;对于NVR前端,根据NVR型号,有4、8、12、16、32路等。
        //设置视频源
        try
        {
            NET_SPLIT_SOURCE[] splitSrcS = new NET_SPLIT_SOURCE[nSrcCount];
            splitSrcS[0] = stSplitSource;
            bRet = NETClient.SetSplitSource(m_LoginHandle, nOutChannel, nWindow, splitSrcS, 3000);
        }
        catch (NETClientExcetion nex)
        {
            Console.WriteLine("Failed to set split source" + nex.Message);
            return false;
        }
        return bRet;
    }

    7.删除某一个解码器视频窗口

    public bool ClientCloseSplitWindow(int nChannel,int nWindowID)
     {
          bool bRet = false;
          NET_IN_SPLIT_CLOSE_WINDOW stCloseWindowIn = new NET_IN_SPLIT_CLOSE_WINDOW();
          stCloseWindowIn.dwSize = (uint)Marshal.SizeOf(stCloseWindowIn.GetType());
          stCloseWindowIn.nChannel = nChannel;
          stCloseWindowIn.nWindowID = nWindowID;
          NET_OUT_SPLIT_CLOSE_WINDOW stCloseWindowOut = new NET_OUT_SPLIT_CLOSE_WINDOW();
          stCloseWindowOut.dwSize = (uint)Marshal.SizeOf(stCloseWindowOut.GetType());
          bRet = NETClient.CloseSplitWindow(m_LoginHandle, ref stCloseWindowIn, ref stCloseWindowOut, 3000); 
          return bRet; 
    }

    9.退出登录

    NETClient.Logout(m_LoginHandle);

    10.释放内存

    NETClient.Cleanup();
  • 相关阅读:
    DBLE快速开始
    RPM包直接安装MySQL
    初试DTLE-单向-聚合-分散复制
    使用 TiUP cluster 在单机上安装TiDB
    如何升级到MySQL8.0
    SpringBoot集成AOP操作日志
    IDEA常用插件
    JAVA中如何实现字符串的反转?
    mysql数据库忘记密码时如何修改密码
    二分查找算法
  • 原文地址:https://www.cnblogs.com/HansZimmer/p/12674641.html
Copyright © 2011-2022 走看看