基於TCP協議的網絡攝像頭的設計與實現


一、摘要

  基於TCP協議的網絡攝像頭的設計大部分和博文“基於UDP協議的網絡攝像頭的設計與實現”相同,本篇博文采用的TCP協議棧為NicheStack協議棧(同理,可使用LWIP協議棧實現),協議分析及上位機設計可參考博文“基於NicheStack協議棧的網絡例程分析及客戶端程序設計”。

 

二、實驗平台

硬件平台:DIY_DE2

軟件平台:Quartus II 9.0 + Nios II 9.0 + Visual Studio 2010

 

三、硬件部分

  該部分可參考博文“基於UDP協議的網絡攝像頭的設計與實現”。

 

四、底層軟件設計及上位機程序

  該篇博文介紹的重點是底層軟件(NIOS II端)和上位機程序的設計,底層和上位機的通信流程圖如下圖所示。

圖 1 底層和PC之間的通信流程圖

  以上是系統的整體流程圖,下面對一些關鍵的調試過程做個闡述。

1、圖像傳輸的基本功能實現

  根據“基於UDP協議的網絡攝像頭的設計與實現”里面的調試經驗,對系統進行調試。

  首先,在C#端,重寫buffer,驗證C#顯示控件的正常。調試圖片如圖2所示。

圖2 C#控件顯示調試圖

  底層的發送數據包長度為1500,TCP數據包的包頭長度為54,所以一包數據可以顯示(1500-54)/2=723個像素,在控件顯示2行83個像素。在控件的頂端細節部分可以看到。

  其次,在NIOS II寫待發送的數據,發送到C#端,驗證顯示正常。這里采用TCP的拉模式。即C#端手動發送一次命令,底層發送上來一包數據,這樣手動發送107次命令之后,C#控件可以顯示出底層發送上來的一幀既定色彩的圖像,如圖3所示。

圖3 底層發送的既定色彩圖像

  再次,在驗證上述2個步驟的基礎上,添加讀取SRAM數據,即將獲取的圖像傳輸上來,並在C#中添加自動發送命令功能,則可以在C#端連續收到圖像數據,如圖4所示。

 

圖4 圖像效果圖

2、圖像傳輸的速度測試及改進

  按照1中的步驟可以將圖像顯示出來,只是速度很低,約30s顯示出一幀圖像,網絡傳輸速度約為10KB/s。之前傳輸慢的原因是,網絡傳輸采用的是拉模式,即C#發一次命令,底層傳輸一包數據,這樣一幀圖像要107次命令,可見效率極低。另外C#端的程序也有造成速度慢的原因。

  改進1:C#端刪除掉不必要的內容,接收及繪圖部分單獨開了一個線程。代碼如下:

        private void TelnetThread()
        {
            while (socket.Connected)
            {
                try
                {
                    Receive();

                    //去掉不必要的輸出,提高接收效率
                    //string str = Receive();
                    ////string str = "";
                    //str = str.Replace("\0", "");
                    //string delim = "\b";
                    //str = str.Trim(delim.ToCharArray());
                    //if (str.Length > 0)
                    //{
                    //    Console.WriteLine(str);

                    //    if (str == OUTPUTMARK + BACK)
                    //    {
                    //        //BackupSpace鍵處理
                    //        this.rtbConsole.ReadOnly = false;
                    //        int curpos = rtbConsole.SelectionStart;
                    //        this.rtbConsole.Select(curpos - 1, 1);
                    //        this.rtbConsole.SelectedText = "";
                    //        this.rtbConsole.ReadOnly = true;
                    //    }
                    //    else
                    //    {
                    //        Log(LogMsgType.Incoming, str);
                    //    }
                    //}
                    Thread.Sleep(100);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }
            }
            this.sbpStatus.Text = "狀態:已斷開";
        }

  這個改進大大提高了C#端的數據接收速度,也解除了不能用for循環連續發送數據包的問題。另外,C#端每收到一幀圖像數據后,自動發送一次命令,使底層繼續傳輸下一幀圖像。

  改進2:底層部分,每發送一包數據,將發送指針指向發送數組的首地址,代碼如下:

    for(j = 0; j < 107; j++)
    {
        //每發送完一包數據,使指針指向數組的首地址
        tx_wr_pos = tx_buf;
        
        for(k = 0; k < 1446; k++)
        {
            if((k%2) == 0)          
                tx_buf[k] = a[k/2 + j*723];
            else
                tx_buf[k] = b[k/2 + j*723];
            tx_wr_pos++;
        }
        //寫滿發送數組之后,將其發送出去
        send(conn->fd, tx_buf, tx_wr_pos - tx_buf, 0);  
            
        printf("NIOS WORKING\n"); 
            
    }

  改進3:底層部分,PIO中斷,每次進入PIO中斷后,先將中斷標志位清零,可是在沒有中斷源的情況下,系統還是頻頻進入中斷服務函數,不知何解?無奈之舉是,進入中斷服務函數之后,直接關閉中斷使能並將中斷標志位清零,等uC/OS II端將圖像數據完全傳輸出去之后,再開啟中斷使能。另外,uC/OS II系統啟動之前,不能開啟中斷使能,所以在初始化的時候應將PIO中斷使能禁止,當收到客戶端的命令時,再開啟中斷使能。該部分的操作流程見圖1。

  通過上述3個方面的改進,傳輸速度大大提高了,約100KB/s,這樣,顯示一幀圖像不到3s,顯示效果也比較清晰。

 

五、總結

  根據上述幾篇博文的闡述,分別完成了基於UDP和TCP傳輸協議的網絡攝像頭的設計與實現,博文重點分析了調試過程,即發現問題、解決問題的過程。博文論證了設計原理的正確性,同時,網絡傳輸的速度也得到了測試,不過仍有許多改進和提高的地方,比如在傳輸的同時,寫下一幀圖像。

  另外一個重點是,博文闡述的圖像壓縮使用的是有損壓縮的方法,最終的分辨率為320*240,rgb555形式。因此,下一步將重點研究圖像編解碼算法,最大限度的降低碼率。使視頻更加流暢。

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM