DirectShow的基本單元 Filter

2021-07-16 09:09:55 字數 2603 閱讀 7157

directshow所採用的是一種模組化的結構,其基本單元是一類成為filter的com物件。directshow提供了多種預定義的標準filter元件,同時開發者也可以根據需要開發自己的個性化filter。常用的filter一般可分為以下不同類別:

(2)transform filter——負責資料的變換處理,獲取輸入資料並對其進行相應處理後,生成輸出資料並傳遞到下乙個filter。典型的如編碼、解碼filter等。

(5)mux filter——用於復用資料流,作用與splitter filter相反。

每乙個filter都至少實現了ibasefilter介面用於實現filter graph中的統一操作。每乙個實現filter的檔案都是動態鏈結庫,可能是dll但更多的是ax檔案。在**中,乙個filter也與其他com物件一樣,通過api: cocreateinstance()建立。

作為乙個com元件,註冊和解除安裝均通過regsvr32.exe程式實現。一般的filter工程會定義一下四個匯出函式:dllgetclassobject,用於建立物件時呼叫,根據clsid返回對應的類廠物件;dllcanunloadnow,用於判斷是否可以從記憶體中解除安裝;dllregisterserver和dllunregisterserver用於元件的自註冊,可以在程式中通過loadlibrary載入dll庫後匯出執行之實現自註冊。所謂「註冊」,就是將filter的基本com資訊寫入登錄檔的操作。

**型別用於規定filter所處理的資料的格式。其定義實際上是乙個am_media_type結構體:

[cpp]view plain

copy

typedef

struct

_mediatype  

am_media_type;  

該結構體中描述**型別的成員主要有majortype, subtype和formattype三部分,分別用於描述**型別、具體格式和格式的細節等。

任何兩個filter之間的相互聯絡通過乙個com物件pin實現,pin的連線實際上是輸出pin和輸入pin之間關於**型別的「協商」過程。每乙個pin都實現了ipin介面,pin物件也是通過這個介面實現連線的。連線過程大致為:

step 1:filter graph manager在輸出pin(上級pin)上呼叫ipin::connect()方法,用輸入pin指標和指定的連線用的**型別作為引數;

step 2:若輸出pin接受連線,則呼叫輸入pin的ipin::receiveconnection()方法;如果輸入pin接受連線,則本次連線成功;

在ipin::connect()的實現函式cbasepin::connect中,首先檢查引數和狀態(如pin是否已經被鏈結、filter是否是停止狀態),隨後檢查**型別,找到雙方都支援的**型別。檢查**型別呼叫了agreemediatype()函式,如果該函式指定的**型別非空,則針對該型別做一次嘗試,如果成功則呼叫attemptconnection嘗試連線;如果**型別指標為空或物件不完整,則呼叫trymedaitypes()遍歷輸入和輸出pin上支援的**型別,對每一中支援的型別呼叫attemptconnection()嘗試連線。

在attemptconnection()中,首先會呼叫輸出pin(上級pin)的checkconnect進行連線檢查(如輸入pin是否支援特殊介面等),若失敗則breakconnect()。成功後呼叫checkmediatype()。若check成功,則講輸入pin和**型別資訊儲存在輸出pin中,隨後呼叫receiveconnection()和completeconnection()完成連線。

在directshow中定義了sample類,是乙個封裝了一定大小資料記憶體的com元件。相互鏈結的filter之間通過sample進行資料傳輸。

在傳輸過程中,兩個鏈結的pin擁有同乙個sample分配器allocator,用於建立和管理sample。傳輸時上級filter通過輸出pin的allocator得到空閒的sample及其記憶體位址,並將資料存放其中,隨後將這個sample傳遞給下級filter的輸入pin。

資料傳輸的兩種主要方式:推模式和拉模式。

①推模式:常用於實時源,自身可以產生資料並通過專用資料線程將資料向下傳遞,具體方法是呼叫下級filter輸入pin的imeminputpin::receive函式實現;

②拉模式:常用於檔案源,源filter輸出pin需實現iasyncreader介面,由下級filter的輸入pin呼叫該介面的方法獲取資料。

* directshow需要專門的執行緒來傳送資料,因此至少需要兩個執行緒(應用程式主線程和資料線程)。

任何filter可能分為三種狀態,即「run」、「stop」和「pause」。通常情況下整個filter graph中的filter都處於同一狀態,那麼這個狀態也成為整個filter graph的狀態。

在具體實現中,每個filter實現了ibasefilter介面,該介面繼承自imediafilter介面,該介面的方法實現了filter的狀態轉換功能。filter graph manager在控制filter graph的執行時,通常呼叫其imediacontrol的run/pause/stop等方法控制。在這些函式的內部,正是呼叫了filter graph內所有的filter的imediafilter::run()、imediafilter::pause()、imediafilter::stop()實現。

DirectShow 的重要介面

directshow 的重要介面 directshow採用了com標準,所以很多重要的功能都是通過com介面來完成。下面就列舉一些重要的directshow的介面。1 igraphbuilder介面 用於構造filter graph的介面,建立和管理一系列的filter,過濾和處理源 流。2 ime...

Directshow的開發環境配置

各位仁兄 序言 這是我的師兄寫給我的關於如何設定directshow開發環境,現在把它資源共享,我也很希望早日寫出自己的正確理解,對於directshow開發指南一書,本人剛剛開始,還學習請大家多多指教。如下 首先,原書中第乙個配製說 確認已經編譯過基類源 生成乙個 我想這裡你可能不知道該怎麼做,具...

系統裝置的列舉(DirectShow)

directshow 對系統中不可預知性硬體提供了良好的支援,其方法是使用系統列舉,系統列舉的一般過程如下所示 1 使用cocreateinstance函式建立系統列舉器組建物件 clsid為clsid systemdeviceenum 並獲得icreatedevenum介面 2 使用介面方法icr...