天天看點

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.cpp的OnInitDialog方法能看到如下兩行代碼:

    MP4_ClientSetNetPort(5050,6050);

    MP4_ClientStartup(WM_MYCOMMAND,this->m_hWnd);

          很明顯這是調用了API,其他代碼就不用管了,那麼我把這代碼翻譯到C# WinForm的Form1_Load事件裡面,并且也這樣調用API(封裝好的SDK請看上篇文章):

            PcHikClient.MP4_ClientSetNetPort(5050, 6050);

            PcHikClient.MP4_ClientStartup(PcHikClient.WM_USER + 1, this.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;

    case 2:

        aa5.m_bSendMode = MULTIMODE;

    case 3:

        aa5.m_bSendMode = DIALING;

    case 4:

        aa5.m_bSendMode = AUDIODETACH;

    default:

    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)

        MP4_ClientSetBufferNum(nn1,40);

        MP4_ClientSetPlayDelay(nn1,580);

        MP4_ClientSetBufferNum(nn1,15);

        MP4_ClientSetPlayDelay(nn1,40);

        MP4_ClientSetPlayDelay(nn1,0);

        MP4_ClientSetBufferNum(nn1,0);

//    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文章裡面我們也能看到這樣的說明。這段代碼最好在窗體關閉的時候也加上!!

下一篇: SSH使用指南

繼續閱讀