龐赫
【摘要】 計算機屏幕圖像的截取在屏幕錄制、計算機遠程控制以及多媒體教學軟件中都是關鍵術。研究的重點集中在如何快速有效的截取DIB(Device-Independent Bitmap)格式的屏幕圖形數據。本文采用一種高性能屏幕截取技術,實現了基于Windows圖形驅動截圖的遠程控制系統。
【關鍵詞】 屏幕錄制 遠程控制 屏幕截取
一、遠程控制系統的系統設計
1.1 系統分析
在視頻會議系統中,共享桌面的客戶端,獲取本地屏幕或者其中特定窗口以及固定區域的圖像變化數據,編碼壓縮,傳輸到服務器端,由服務器端將該數據分發到個個接收端。接收端解碼圖像數據,即可觀看到共享桌面。圖像的數據量很大,為了達到發送獲取壓縮,接收解壓播放的高性能,該部分的編碼采用非托管實現。整個視頻會議系統是.NET平臺下,所以該部分代碼采用組件開發模型[1],方便系統的調用也符合軟件開發的N層構架的要求[2]。
1.2系統結構設計
圖1 客戶端與服務器的C/S構架模型
在C/S模式構架的程序中,客戶端的所有交互都是通過服務器的中轉完成。共享桌面的客戶端在開啟共享之后。桌面的圖像數據經過編碼壓縮會發送到服務器端,經過服務器的分發,圖像數據會被分發到N-1個客戶端,這就要求服務器有足夠的上行和下行帶寬。客戶端接收到屏幕圖像數據,經過解碼解壓播放圖像數據,根據實際的網絡狀況可能會有不同程度的延時。共享桌面的客戶端(一般為教師機器),可以指定一個控制端,開啟遠程控制。被授權的客戶端會把包括鼠標坐標,鼠標鍵的點擊彈起,鍵盤按鍵的點擊和彈起消息進行封裝,經服務器傳送到共享桌面的客戶端。該客戶端接收到遠程控制信息,模擬本地的輸入操作,達到遠程控制的效果,構架模型如圖1所示。
圖2 共享桌面客戶端發送屏幕圖像數據
所有客戶端在程序啟動的時候,啟動MirrorDriver,MirrorDriver會把屏幕的鏡像位圖數據和屏幕變化記錄填充到緩沖區內,如果共享桌面的客戶端開啟共享。為了程序的執行效率,以多線程的形式啟動桌面數據壓縮線程(在主程序運行之外的另外一個線程)。圖像編碼的過程是比較消耗CPU資源的,但是高效率的編碼可以很大程度上節省網絡資源,所以編碼線程在另外一個線程中執行,可以保障主程序的流暢運行。編碼的過程中需要兩個緩沖區,輸入緩沖和輸出緩沖區。MSScreen的DMO壓縮需要手動填充輸入緩沖區。從屏幕鏡像緩沖區中取出圖像數據,把輸入緩沖區的地址指針給DMO,編碼后的數據會被填充到輸出緩沖區內,并返回輸出數據的字節大小,這個過程是自動完成的。編碼正確完成之后,從輸出緩沖區取出數據,遞交給網絡線程就可以發送了。發送的過程和主程序的其他數據發送模式一致,所以屏幕共享模塊可以很容易的集成到主項目中,而不需要單獨的發送和接收,如圖2所示。其他客戶端(一般是學生機器客戶端),接收到教室機器的共享屏幕數據之后。數據從網絡線程接收,同樣是多線程的處理方式。解碼的過程類似與編碼的逆過程。輸入緩沖區存放接收到的數據。輸出緩沖區存放的是圖像數據。因為視頻的壓縮需要關鍵幀,如果客戶端剛好接收到的第一幀不是關鍵幀,解壓出來的位圖為全黑色,直到接收到關鍵幀之后可以正確解碼出圖像,如圖3所示。
二、遠程控制系統的系統實現
2.1獲取屏幕最小變化部分
在處理屏幕發送當中,第一次請求或在以后需要發送整屏數據(例如:監視區域發生變化,或在一次發送周期中的變化數據總和大于整屏數據量或客戶終端主動請求發送整屏數據的情況)。為了處理上述情況,使用兩個臨時數據full_rgn、incr_rgn。如遇到上述情況,例如第一次連接時,程序在處理過程中使變量!full_rgn.IsEmpty()返回值>0。所以發送之前只要檢查m_full_rgn既可,如果遇到需要發送全屏的情況,incr_rgn.Clear()(在此周期中的更新數據區域清空)。驅動返回的更新記錄是即時的,沒有必要即時發送數據。因為系統資源的占用消耗,捕捉到更新區域既可,遠程沒有必要即時發送。其次就是數據量的原因,對于遠程發送,較少的數據量可以有效的節省網絡帶寬資源。
圖4 屏幕變化部分 圖5 屏幕變化部分
如圖4所示,兩次連續的變化(在極短時間周期內,即在一次獲取變化數據周期內),兩次更新的區域有重疊,而這種情況在屏幕變化時是經常發生的。而驅動只會記錄下變化的區域而已。如果適當的采用優化算法,不僅可以有效的減小冗余數據,而且可以降低對資源的消耗。在實際應用過程當中是非常實用的。如果采用相應的算法,就不會出現一個周期內的變化數據總和大于整屏幕數據,如圖5所示。
對第一種的解釋是驅動的在共享數據中的標識,標識該區域是在屏幕內是移動的,由上一區域和當前區域可以計算出位移向量(例如窗口的拖動,該標記由驅動完成,應用程序只負責處理該情況)。為了節省數據發送量可以假定只發送更新矩形,和源矩形的左上坐標。把該消息發送客戶端,由客戶端完成虛擬屏幕的拖動,只需要完成數據內部的拷貝。這樣可以節省大量數據的發送,(因為變化的數據只是在已有數據中位置的變化)。但是存在一種特殊情況,位移的矩形很小的時候,程序中假定的大小是矩形的長寬都小于一個16(int),如果矩形很小,還是采用上述方法相對來講效率不會比不考慮其特殊性高,甚至效率更低。
2.2屏幕圖像多線程壓縮及解壓實現
如圖6所示,在程序啟動之后,進行資源的初始化。如果允許共享,初始化桌面壓縮線程。壓縮和發送數據都是多線程的,不是在同一個線程,但是線程同步的,數據委托給網絡線程發送。每執行一個周期,將事件狀態設置為非終止狀態,導致線程阻止。當定時器達到下一次周期時,將事件狀態設置為終止狀態,允許等待線程繼續。
圖6多線程壓縮桌面圖像
三、結束語
圖像數據的傳輸,難點在于數據量的大小。網絡數據量的大小直接關系到軟件的性能和質量,在程序設計之初,擬采用JPEG圖片靜態壓縮算法,雖然在一定程度上減低了數據量,但是并不能達到高效。因為屏幕的圖像區別與其他位圖圖像,所以采用專門的屏幕壓縮算法可以更有效減小數據量。程序在后續的改進中,采用微軟的Screen壓縮算法,在5 frame/s 網絡數據量可以降低到15 k/s,并確保圖像質量清晰,在網絡狀況不是很好的時候也可以保證程序的流暢運行。高效的壓縮算法對CPU的使用也是比較高的,多線程的處理數據的壓縮,可以保證程序流暢運行。
參 考 文 獻
[1] Ted Faison. Visual C#基于組件的開發. 北京:清華大學出版社.2003,4
[2] Robert C.Martin,Micah Martin.敏捷軟件開發:原則、模式與實踐(C#版). 北京:人民郵電出版社. 2008,1