一、摘要
基於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形式。因此,下一步將重點研究圖像編解碼算法,最大限度的降低碼率。使視頻更加流暢。