劉立才,康維新,王海生,繆 晶,張 強,李 鵬,吳學文
(1.哈爾濱工程大學信息與通信工程學院,黑龍江 哈爾濱 150001;2.華北電力大學控制與計算機工程學院,北京 102206;3.黑龍江省哈雙高速公路管理處,黑龍江 哈爾濱 150090)
責任編輯:任健男
隨著Linux在中國的普及,必須保證能夠用Linux實現(xiàn)其他操作系統(tǒng)(如Windows系列操作系統(tǒng))下的功能,如文字處理、電子表格、上網(wǎng)等,也就是說,必須有大量圖形用戶接口(GUI)應用程序滿足用戶各方面的需求[1]。而基于Linux下的C/C++語言的GUI編程有多種方案,較為流行的有基于QT庫和基于GTK+/GNOME兩種。KDE(K Desktop Environment)曾經(jīng)是Linux下最流行的用QT庫開發(fā)的桌面環(huán)境,但是,KDE依賴于Troll Technologles公司所開發(fā)的QT庫[2],該庫許可證的獲得非常困難。所以,應該避免使用 QT 庫及 KDE[3-5]。
基于上述原因,本項目采用GTK+/GNOME函數(shù)庫研究客戶端用戶界面設計。該庫僅需XLIB、GLIB(圖形底層函數(shù)庫)和GDK庫的支持,且這些庫操作簡便,同時GTK具有移植性好、可定制、占用空間小、運行穩(wěn)定等優(yōu)點,加之它模塊化設計和全C編寫的特性,使得GTK不但應用在專用嵌入式系統(tǒng)上,也可以在通用PC機上使用,出于這種考慮,采用GTK開發(fā)GUI應用程序比較合適[6]。
由客戶端軟件構成的系統(tǒng)整體架構如圖1所示。該系統(tǒng)大致由通信協(xié)議端程序、服務器端程序和客戶端程序三部分組成。由于篇幅所限,這里重點研究客戶端程序的設計,具體包括基于GNOME桌面環(huán)境下GTK圖形用戶界面的設計以及視頻采集客戶端程序的設計過程。而對于通信協(xié)議端程序和服務器端程序的設計,這里只簡單介紹它們在整個系統(tǒng)中所實現(xiàn)的功能。其中通信協(xié)議端程序所實現(xiàn)的功能有:通過該協(xié)議能夠將服務器采集的視頻數(shù)據(jù)傳輸?shù)娇蛻舳?能夠將攝像頭圖像屬性,如對比度、分辨力等信息傳遞給客戶端;通過該協(xié)議客戶端能夠控制服務器端攝像頭改變采集的圖像屬性;在客戶端程序退出時能夠通知服務器一般進行后續(xù)處理。

圖1 系統(tǒng)總體架構
服務器端程序實現(xiàn)的功能有:實現(xiàn)基于多線程的循環(huán)服務器;傳輸層基于TCP/IP協(xié)議進行通信;通過V4L2接口獲取攝像頭采集數(shù)據(jù);通過V4L2接口設置攝像頭圖像屬性,如對比度、分辨力等;應用層通過自定義通信協(xié)議與客戶端進行通信;根據(jù)命令行參數(shù)初始化攝像頭。
客戶端程序實現(xiàn)的功能有:傳輸層基于TCP/IP協(xié)議進行通信;應用層通過自定義通信協(xié)議與服務器進行通信;用戶界面基于GNOME桌面環(huán)境,并利用GTK進行開發(fā)。
主函數(shù)程序設計流程如圖2所示,程序開始運行時先進行必要的初始化操作,先通過判斷函數(shù)g_thread_supported()的值,如果該函數(shù)的返回值為true,則說明線程已經(jīng)初始化,否則要調用g_thread_init()函數(shù)進行線程初始化,接著要依次對GDK庫和GTK庫進行初始化操作。然后創(chuàng)建并啟動攝像頭運行線程來完成客戶端視頻采集的功能。如果這時在連接界面中能夠通過Connect按鈕成功連接至服務器端,則立即通過調用函數(shù)create_main_app()進入視頻監(jiān)控界面并進行實時視頻圖像的顯示。在視頻監(jiān)控界面下,程序會停留在gtk_main()處,直到用戶驅動某事件后被主循環(huán)捕獲到,要根據(jù)事件攜帶的窗口ID信息決定接收的構件,然后將信息格式化后以信號的形式傳給構件,最后構件調用關聯(lián)的回調函數(shù)進行處理操作。有關連接界面和視頻監(jiān)控界面的軟件設計將在下面詳細研究。

圖2 主程序的軟件流程
根據(jù)功能需求,客戶端所設計的連接界面在頂層窗口下建立的構件區(qū)主要由圖片區(qū)、輸入?yún)^(qū)、按鈕區(qū)和狀態(tài)區(qū)構成。圖片區(qū)插入圖片構件的目的是使整個界面更加美觀、更具個性化,這里采用哈爾濱工程大學標志性建筑作為應用圖片。對于界面輸入?yún)^(qū)主要由標簽和輸入條構成,它主要完成人機交互的功能。即用戶可以在輸入條中輸入要連接服務器端的IP地址和端口號。按鈕區(qū)由Connect和Quit兩個按鈕構成,主要負責建立C/S之間的連接以及退出連接界面的操作。而當鼠標在上述三個區(qū)域動作時,就會在狀態(tài)區(qū)顯示相應操作的狀態(tài)信息。客戶端連接界面的軟件設計是在主程序中通過調用connect_app()函數(shù)來實現(xiàn),此函數(shù)具體的軟件實現(xiàn)如圖3所示。可見,函數(shù)init_conn_if()的調用是用來完成圖片區(qū)、輸入?yún)^(qū)、按鈕區(qū)和狀態(tài)區(qū)的創(chuàng)建過程,具體軟件流程如圖4所示。界面軟件設計中各個區(qū)域的界線由新建的分割線構件構成,且在圖4中每個調用函數(shù)中都要完成相應區(qū)域中各個構件的生成、構件屬性的設置、構件擺放位置的設定以及當用戶驅動某事件產(chǎn)生相應信號傳遞給某構件后,構件處理事件所需關聯(lián)回調函數(shù)的編寫等任務。圖5為運行客戶端軟件時所生成的連接界面,可見,達到了所要設計的預期。



由于用戶實際應用的需求,客戶端所要設計的視頻監(jiān)控界面大致分為視頻區(qū)、狀態(tài)區(qū)、設置區(qū)和按鈕區(qū)四部分。視頻區(qū)主要負責實時視頻的監(jiān)控,同時還可以根據(jù)監(jiān)控圖像的畫質情況,在設置區(qū)設置服務端攝像頭的圖像屬性,如圖像的亮度、對比度、分辨力、銳利度、灰度系數(shù)等參數(shù)。設置后可通過點擊按鈕區(qū)中的設置按鈕實時對服務端攝像頭采集的視頻幀進行設置與控制,同時服務端又會將設置攝像頭后的圖像屬性通過自定義通信協(xié)議實時返回給客戶端,所以在客戶端監(jiān)控界面上這些信息將在狀態(tài)區(qū)中得到實時顯示。這些功能的軟件實現(xiàn)主要通過自定義函數(shù)create_main_app()來完成。在主程序運行過程中,當客戶端成功與服務端建立連接后,也就是connect_app()函數(shù)被成功調用后,程序會立即執(zhí)行自定義函數(shù)create_main_app()來生成視頻監(jiān)控界面,該函數(shù)的具體軟件實現(xiàn)如圖6所示。圖中函數(shù)video_status_setup()的作用是初始化采集的同時也完成填充全局狀態(tài)結構的工作,使界面顯示后體現(xiàn)出如設備名稱、服務器、端口號、捕獲幀大小、分辨力以及用戶控制和設置等項的狀態(tài)信息。自定義函數(shù)init_main_if()調用主要完成視頻監(jiān)控界面的整體布局和層次分配,它的軟件實現(xiàn)如圖7所示,每個區(qū)的建立通過調用相應的實現(xiàn)函數(shù)來完成,而相應實現(xiàn)函數(shù)所要實現(xiàn)功能具體包括各個構件的生成、構件屬性的設置、構件擺放位置的設定以及當用戶驅動某事件產(chǎn)生相應信號傳遞給某構件后,構件處理事件所需關聯(lián)回調函數(shù)的編寫等。客戶端軟件運行時所生成的視頻監(jiān)控界面如圖8所示,該界面的監(jiān)控區(qū)域畫面圖像清晰、流暢,且整個界面工作穩(wěn)定。



圖8 客戶端監(jiān)控界面的設計(截圖)
為了克服多進程在軟件設計上占用系統(tǒng)資源多、運行效率低和響應速度慢等缺點,更好地保證視頻數(shù)據(jù)及時處理,滿足視頻圖像實時性的要求,本項目采用Linux環(huán)境下具有并發(fā)性更高的多線程處理技術。通過調用線程執(zhí)行函數(shù)cam_thread()對視頻數(shù)據(jù)進行各種處理操作。在主程序開始運行并初始化后,通過調用攝像頭運行線程來完成客戶端視頻采集的功能。該函數(shù)的具體軟件實現(xiàn)過程如圖9所示。圖中g_bcamoff為關閉設備標識符,g_bcamrun為正在視頻采集標識符。程序運行過程中根據(jù)查詢到不同階段這兩個標識符的狀態(tài),來完成相應的處理操作。函數(shù)cam_get_img()的調用主要完成的工作是客戶端向服務端發(fā)出獲取攝像頭采集數(shù)據(jù)的命令,服務器正常響應后,通過自定義通信協(xié)議,把相應采集到的一幀數(shù)據(jù)發(fā)送給客戶端,客戶端根據(jù)與之對應的自定義通信協(xié)議,從套接字中得到該幀并把它讀取到相應的視頻緩沖區(qū)。隨后調用gwin_draw_area()函數(shù)將緩沖區(qū)中的該幀視頻數(shù)據(jù)實時地更新到用戶監(jiān)控界面中去。可見此線程的重要性,它成功創(chuàng)建與否直接決定整個軟件運行狀況。
在客戶端軟件運行過程中,主函數(shù)通過調用工作線程來完成視頻幀數(shù)據(jù)的獲取及處理操作。如果在工作線程運行過程中,客戶端從服務端得到的一幀新視頻數(shù)據(jù)不經(jīng)任何處理直接更新到視頻監(jiān)控界面中,將會出現(xiàn)與工作線程沖突的情況發(fā)生,導致視頻監(jiān)控界面出現(xiàn)假死的狀況,造成整個軟件不能正常工作。為了防止視頻監(jiān)控界面在進行界面更新時出現(xiàn)界面假死的情況。這里在工作線程中采取創(chuàng)建子界面線程的編程方法來加以克服,它是通過調用自定義gwin_draw_area()函數(shù)來實現(xiàn)。此函數(shù)定義如下:

圖9 攝像頭運行線程

此線程執(zhí)行函數(shù)的功能就是在修改界面語句前加gdk_threads_enter()進入修改界面的線程鎖定,修改完界面后再使用gdk_threads_leave()解除鎖定。這樣就可以避免界面線程與工作線程沖突所導致的監(jiān)控界面假死情況的發(fā)生,使得界面得到及時的更新,這也是保證視頻監(jiān)控界面實時性好的關鍵所在。所以,該處理技術在本軟件設計中最為重要。
本文在Linux環(huán)境下充分利用多線程編程方法和GTK+/GNOME技術的優(yōu)點,結合現(xiàn)代通信傳輸技術,對能夠處理實時視頻數(shù)據(jù)的客戶端軟件進行了詳細設計分析。經(jīng)過測試該客戶端軟件性能可靠穩(wěn)定,所設計的視頻監(jiān)控界面不但協(xié)調、美觀,而且由該軟件構成的監(jiān)控系統(tǒng)的監(jiān)控畫面清晰、流暢、實時性好,克服了界面在工作過程中遇到的界面假死等現(xiàn)象。此外,如果將無線監(jiān)控系統(tǒng)客戶端和服務端的功能繼續(xù)加以完善,可以根據(jù)不同終端的IP及端口號進行音視頻雙向通信,就能從根本上解決在嵌入式移動終端上依據(jù)IP技術實現(xiàn)網(wǎng)絡任意節(jié)點間點對點通信的難題,這也是后續(xù)研究的重點課題。
[1]許宏松,吳明行.Linux應用程序開發(fā)指南使用Gtk+/Gnome庫[M].北京:機械工業(yè)出版社,2000.
[2]HARLOW.實用技術:Linux中Gtk+和GDK開發(fā)Linux圖形界面應用[M].北京:電子工業(yè)出版社,2000.
[3]陳健.Linux高級程序設計[M].北京:人民郵電出版社,2008.
[4]閆娟,程武山,孫鑫.基于嵌入式Linux的實時網(wǎng)絡視頻監(jiān)控系統(tǒng)[J].電視技術,2006,30(12):81-84.
[5]宋國偉.GTK+2.0編程范例[M].北京:清華大學出版社,2002.
[6]戰(zhàn)曉蘇.GTK+程序設計C語言版[M].北京:清華大學出版社,2002.