• 沒有找到結果。

模組間數據傳輸機制

第二章 模組間內部機制介紹

2.2 模組間工作原理

2.2.3 模組間數據傳輸機制

因此在 DecideAllocator 函式中首先會先去詢問輸入 Pin 是否提供 Allocator,

如果提供便呼叫 DecideBufferSize 函式來設定 Allocator 的特性,如果不提供 則必須由輸出 Pin 來建立 Allocator 並設定特性,當 Allocator 配置完成整個模 組間的連接才算真正的完成。

2.2.3 模組間數據傳輸機制

前面已經提到 Filter 之間如何成功的連接,接著本節即將繼續探討第二個 問題 Filter 之間如何傳輸數據。在 DirectShow 中有一條專門負責傳輸的線程 (Thread)稱為傳輸執行緒,因此我們以下會介紹這條執行緒如何建立以及建立後 如何傳輸,而圖 2-7 是一個傳輸機制的整體流程圖,我們將藉由這個圖來說明 DirectShow 透過怎樣的機制來解決數據傳輸的問題。

9

圖 2-7 傳輸機制流程圖

10

1. 當使用者按下 Run 後,便將 Run 命令傳送給 Filter Graph Manager。

2. Filter Graph Manager 便啟動 Source Filter 的 Active()函式開始執行,

Active 函式程式碼如圖 2-8 所示。

圖 2-8 Active 函式程式碼

我們可以看到 Activec 函式會先把目前狀態鎖住,接著檢查 Source Filter 是否為 Active 狀態,以及檢查 Source Filter 是否連接,必須是在 Active 狀態 以及 Filter 是連接的狀態才可以繼續下面的動作。

3. 通過以上檢查後,Active 函式就會透過 Init()函式發出 CMD_INIT 的命令,

Filter Graph Manager 收到 CMD_INIT 命令後就會啟動 ThreadProc()函式開 始執行,ThreadProc 函式程式碼如圖 2-9 所示。

11

圖 2-9 ThreadProc 函式程式碼

4. ThreadProc() 函 式 先 確 定 目 前 確 實 是 CMD_INIT 命 令 後 , 才 會 透 過 OnThreadCreate()函式建立一條傳輸執行緒,當傳輸執行緒建立起來後,接 著便進入一個重覆檢查狀態的 while 迴圈,迴圈中將檢查四種狀態,分別對 應的動作如下

z Pause :啟動 DoBufferProcessingLoop 函式開始執行

z Run :觸發 Pause 狀態(因為 DirectShow 規定,要轉換到 Run 或 Stop 都 必須先經過 Pause 的狀態)

z Stop :觸發 Pause 狀態

z Exit :啟動 OnThreadDestory()函式執行銷毀釋放傳輸執行緒的動作 5. 因此除了 Exit 狀態外,其他狀態其實都會啟動 DoBufferProcessingLoop 函

式 , 其 函 式 程 式 碼 如 圖 2-10 所 示 , 而 這 函 式 一 開 始 會 先 透 過 OnthreadStartPlay 函式啟動傳輸執行緒準備做傳輸的動作,接著會檢查是 否有收到狀態的命令,有接收到才繼續檢查目前狀態是否為 Stop 狀態,若是 Stop 就 發 出 Exit 指 令 銷 毀 釋 放 執 行 緒 , 若 不 是 Stop 就 透 過 GetDeliverBuffer()函式向 Allocator 要求一個空的 Sample,並傳給 Source Filter 的 Fillbuffer()函式做一個填充資料的動作,接著 FillBuffer()函 式將回傳填充的狀況,當狀況為填充失敗或其他時將把要來的空 Sample 釋放

12

掉,並回到 ThreadProc 函式中的重覆檢查狀態的樣子,當狀況為填充成功時 就會透過 Deliver()函式來做傳送的動作,如果傳送成功 Transform Filter 的 Receiver()函式就會接收到 Sample,反之則一樣回到 ThreadProc 函式中 的重覆檢查狀態的樣子。

圖 2-10 DoBufferProcessingLoop 函式程式碼

6. 當 Transform Filter 透過 Receiver()函式接收到 Sample 後就會先呼叫 InitalizeOutputSample()函式向 Allocator 要求一個空的 Sample 以便作為 傳送到下一級的準備,接著便把接收到的 Sample 以及要求的空的 Sample 傳 給本身的 Transform()函式做影像處理等動作。

7. Transform()函式做完處理後會把處理完的資料直接填充到準備好的那個空 的 Sample 中,填 充成功便回傳 S_OK ,反之則回傳 S_FALSE 並且回到 DoBufferProcessingLoop()函式。

8. 若收到 S_OK 代表填充成功便會呼叫 Render Filter 的 Receiver()函式來做 一個接收的動作,當 Render Filter 接收到 Sample 就呼叫 Render()函式做 播放的動作,撥放完就釋放 Sample,接著就又回到 DoBufferProcessingLoop() 函式做下一回合的傳輸。

13