大华解码器二次开发/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();

 

posted @ 2020-04-10 17:09  超级驼鹿  阅读(1550)  评论(0编辑  收藏  举报
/*