• 沒有找到結果。

處理影像資料

三、 Java 多媒體系統動態分析

3.3 Thread之間的資料分享與溝通

3.3.2 Thread的設計原理與制衡

3.3.2.1 處理影像資料

此小節說明處理影像Thread 的設計原理與制衡機制。在圖 3-4 中,處理影

像資料的 threads 會執行各自的任務,所有箭頭的起始點和終點表示為各個 thread 所必須要處理的物件,以及物件內的暫存器,其中 bufferQ1 有 8 個 queue,bufferQ2 有 1 個 queue,前兩者的 queue 都為儲存一張照片的大小。

bufferQ3 有 5 個 queue,每個 queue 都為儲存一預設 RTP 封包的大小。

Thread0:VFW RequestThread(V) Thread1:PushThread (V)

Thread2:VFW TransferDataThread (V) Thread3:SourceThread(V)

Thread4:RawBufferStream Thread(V) Object Thread Path

RawBufferParser buffer1 bufferQ2

以下會針對每一個thread 的設計概念做說明,當有對 bufferQ1、bufferQ2 或bufferQ3 作處理時,都會啟動同步機制,此 3 個物件會宣告為 synchronized(請 參考 3.6.3~3.6.6 節)。

Thread0:負責管理 camera,如開啟 camera。除非有其它 thread 要求它改變狀 態,否則當它取得執行權時,並不會做任何程序就會再度回到待命狀態。

Thread1:負責從 camera 取得影像資料,並存入 bufferQ1。

由於擷取影像資料的時間點不能太近,並且希望盡量達到公平的排程,因此 使用sleep(time)函式,使得 Thread1 休眠數豪秒後再起來執行,並且使用 yield() 函式,若Thread1 此次已執行過,下一次的執行機會能讓給其它的 thread,以 上流程如圖 3-5。

接著必須檢查bufferQ1可否放入資料,當無法放入資料時,表示已有8張照 片未處理,因此會清除在bufferQ1內最早放入的照片。接著將擷取的影像資料放 入一暫存器buffer,再將buffer內的資料放入bufferQ1,此時會執行bufferQ1.

notifyAll()函式,此函式主要為通知Thread2隨時可取走資料,接著將記錄buffer 資料量的參數設為0(接下說明相同的程序時都稱之為「清空暫存器」),為下一 次的影像資料做準備。以上流程如圖3-5。

圖3-5 PushThread(V)

Thread2:負責將bufferQ1內的資料搬運至bufferQ2。

首先必須要確定兩件事:1.Thread2可以取得影像資料,因此會檢查bufferQ1 可否讀出資料,若無法取得影像資料Thread2就會在此等待影像資料。當確定可 以取得影像資料時,必須確定另一件事:2.Thread2可否將資料放入bufferQ2,因 此會檢查bufferQ2可否放入資料,當判定無法放入資料時,Thread2會在此等待 Thread3將bufferQ2內的資料取走。

當上述兩件事都成立時,才會開始執行真正資料搬運的動作。首先,會先宣 告一暫存器buffer,將bufferQ1內的資料放入buffer,並且清空bufferQ1所存放

此資料的queue。接著再將buffer內的資料放入bufferQ2,並執行bufferQ2.

notifyAll()函式,通知Thread3隨時可取走資料。以上流程如圖3-6。

圖3-6 VFWTransferDataThread(V)

Thread3:負責自bufferQ2讀出資料後,對取出的資料做壓縮的處理,同時切割 為數個封包,並且依序放入bufferQ3。

首先必須確定Thread3能否取得影像資料,因此檢查bufferQ2可否讀出資 料,當無法自bufferQ2讀出資料時,Thread3會等待Thread2將影像資料放入 bufferQ2。

當Thread3可以自bufferQ2讀取資料時,宣告一暫存器buffer1,將bufferQ2 的資料放入buffer1,接著清空bufferQ2並通知Thread2隨時可放入新的影像資 料。將資料暫時存入buffer1是為了要對資料壓縮的處理做準備,當buffer1的資 料壓縮好並切割為封包大小後放入buffer1`,接著buffer1`所存的封包必須要逐 一放入bufferQ3。

因此必須檢查bufferQ3可否放入資料,當無法放入資料時,Thread3會等待 Thread4取出bufferQ3內的封包。當Thread3可以將封包放入bufferQ3時,會宣 告一暫存器buffer,接著將buffer1`內的封包放入buffer,再將buffer內的封包逐

一放入bufferQ3,並且告知Thread4隨時可將封包取出。

最後Thread3會檢查自buffer送出的封包是不是為最後一個封包,若是最後 一個封包,則Thread3會等待一段時間,此做法是希望再壓縮下一張照片前,

Thread4已將此次照片相關的封包都發送自網際網路,當Thread4發送出最後一 個封包時就會通知Thread3可以壓縮下一張照片。以上流程如圖3-7。

圖3-7 SourceThread(V)

Thread4:負責將bufferQ3內的封包一一讀出,建構為RTP封包,並交給Socket 發送。

首先Thread4必須確定是否有封包要發送,因此必須檢查bufferQ3可否讀出 資料,若判定無法讀出資料,Thread4則會等待Thread3將封包放入bufferQ3。

當Thread4可以自bufferQ3讀出封包時,宣告一暫存器buffer,接將bufferQ3內 的封包放入buffer,接著檢查buffer內所存的是不是為最後一個封包,若是最後 一個封包,Thread4會通知Thread3可以壓縮下一張照片。最後清空bufferQ3內 存放此次封包的queue。以上流程如圖3-8。

圖3-8 RawBufferStreamThread(V) (2) Thread制衡機制

由上述各個thread 的執行概念,下圖 3-9 為暫存器可能管理的 thread 之整 理。bufferQ1 可能管理 VFWTransferDataThread(V),藉由封鎖時間的結束,

VFWTransferDataThread(V) 可 自 動 解 開 bufferQ1 的 封 鎖 , 或 是 由 PushThread(V) 將 資 料 放 入 bufferQ1 時 , 通 知 bufferQ1 解 除 VFWTransferDataThread(V) 的 封 鎖 , VFWTransferDataThread(V) 隨 時 可 自 bufferQ1 讀取資料。

bufferQ2 可能管理 VFWTransferDataThread(V)或 SourceThead(V),也意 味著此兩個thread 同時是藉由 bufferQ2 來溝通。當 VFWTransferDataThread(V) 無法將資料放入bufferQ2 時,此 thread 會被 bufferQ2 封鎖,直到 SourceThead(V) 通 知 bufferQ2 解 除 對 VFWTransferDataThread(V) 的 封 鎖 時 , VFWTransferDataThread(V)就會得知可以將資料放入 bufferQ2 的通知。反之 亦然。

bufferQ3 可能管理 SourceThead(V)或 RawBufferStreamThread(V) ,也意 味著此兩個 thread 同時是藉由 bufferQ3 來溝通。當 SourceThead(V)無法將資 料 放 入 bufferQ3 時 , 此 thread 會 被 bufferQ3 封 鎖 , 直 到

RawBufferStreamThread(V)通知 bufferQ3 解除對 SourceThead(V)的封鎖時,

SourceThead(V)就會得知可以將資料放入 bufferQ2 的通知。

當RawBufferStreamThread(V)無法自 bufferQ3 取得封包時,會被 bufferQ3 鎖住,此thread 可藉由封鎖時間結束而自動結束封鎖,或是 SourceThead(V) 將封包放入bufferQ3 時,會通知 bufferQ3 解除對 RawBufferStreamThread(V) 的封鎖。

圖 3-9 buffer manage(V)

由Thread 的設計原理可知 SourceThead(V)和 RawBufferStreamThread(V) 之間還外加有一控制機制。當SourceThead(V)壓縮並送出最後一個封包時,必 須進入封鎖狀態,等待RawBufferStreamThread(V)將 bufferQ3 內的最後一個 封包發送出去時,SourceThead(V)就會解開封鎖繼續壓縮下一張照片。如圖 3-9 的右下方。

(3)暫存器狀態判斷機制

由前,對於Thread間的制衡機制的介紹,可知必須要有相關機制加以判斷 暫存器是否可以被放入或是讀取資料。當要判斷可否自暫存器讀出資料時,呼叫 canRead( )函式,此函式會檢查記錄暫存器資料量的參數是否大於零,當大於零 時,會回傳一true的布林值,表示此暫存器內存有資料。當要判斷可否放入資料

時,呼叫canWrite( )函式,此函式會檢查記錄暫存器剩餘空間的參數值是否為

RawBufferParser buffer1 bufferQ2 Thread2:DirectSound PushThread (A) Thread3:SourceThread(A)

Thread4:RawBufferStream Thread(A)

Object buffer

Thread Path

1

2

相關文件