使用 DMO 類別範本
[與此頁面相關聯的功能,DirectShow是舊版功能。 它已被 MediaPlayer、IMFMediaEngine和媒體基礎結構中的音頻/視頻擷取取代。 這些功能已針對 Windows 10 和 Windows 11 進行優化。 Microsoft強烈建議新程式代碼盡可能在媒體 基礎中使用 MediaPlayer、IMFMediaEngine 和 音訊/視訊擷取,而不是 DirectShow。 Microsoft建議使用舊版 API 的現有程式代碼,盡可能改寫成使用新的 API。]
DirectShow 包含類別範本,IMediaObjectImpl,用於實作 DMO。 範本會處理許多「記帳」工作,例如驗證輸入參數。 藉由使用範本,您可以專注於 DMO 特有的功能。 此外,範本可協助您確保建立健全的實作。 範本定義於位於 SDK Include 目錄的標頭檔 Dmoimpl.h 中。
IMediaObjectImpl 範本會繼承 IMediaObject 介面。 若要使用範本建立 DMO,請定義衍生自 IMediaObjectImpl的新類別。 此範本會實作所有 IMediaObject 方法。 在大部分情況下,範本會在衍生類別上呼叫對應的私用方法。 此樣本提供下列功能:
- 基本參數檢查。 範本方法會確認必要的參數未 NULL、數據流索引在範圍內,且旗標有效。
- 鎖定。 範本方法會呼叫兩個內部方法,Lock 和 Unlock,以串行化 DMO 上的作業。 這項功能可確保 DMO 執行緒安全。
- 媒體類型。 範本會儲存用戶端所設定的媒體類型,並提供媒體類型的存取子方法。
- 串流。 範本會防止串流處理,直到客戶端設定所有非選擇性數據流的媒體類型為止。 它也可確保在串流開始之前,先呼叫 IMediaObject::AllocateStreamingResources 方法,以確保已配置資源。
衍生類別必須實作 IUnknown 介面;範本不提供此介面。 您可以使用 Active Template Library(ATL)來實作 IUnknown,或者提供其他一些實作。 範本也不會實作鎖定機制。 衍生類別必須實作 Lock 和 Unlock 方法。 如果您使用 ATL 建立類別,您可以使用預設 ATL 實作。
宣告衍生類別
IMediaObjectImpl 類別範本宣告如下:
template <class _DERIVED_, int NUMBEROFINPUTS, int NUMBEROFOUTPUTS>
class IMediaObjectImpl : public ImediaObject
這三個範本參數是 _DERIVED_、NUMBEROFINPUTS 和 NUMBEROFOUTPUTS。 將 _DERIVED_ 設定為等於類別的名稱。 其他兩個參數會定義 DMO 上的輸入數據流和輸出數據流數目。 例如,若要建立名為 CMyDmo 的 DMO 類別,以支援一個輸入數據流和兩個輸出數據流,請使用下列宣告:
class CMyDmo : public IMediaObjectImpl<CMyDmo, 1, 2>
本節的其餘部分說明範本如何在 IMediaObject 中實作各種方法。
媒體類型設定的方法
下列方法會在 DMO 上設定或擷取媒體類型:
- GetInputTypeGetOutputType。 這些方法會依數據流編號和類型索引傳回慣用的媒體類型。 範本會在衍生類別上呼叫 InternalGetInputType 或 InternalGetOutputType。
- SetInputType,SetOutputType。 這些方法會在數據流上設定媒體類型、測試媒體類型或清除媒體類型。 若要驗證媒體類型,範本會在衍生類別上呼叫 InternalCheckInputType 或 InternalCheckOutputType。 衍生類別會傳回 S_OK 以接受該類型,或傳回 DMO_E_INVALIDTYPE 以拒絕該類型。 模板會處理設定或清除媒體類型。
- GetInputCurrentTypeGetOutputCurrentType。 這些方法會傳回串流的當前媒體類型,如果沒有設定類型,則回傳 DMO_E_TYPE_NOT_SET。 範本會完全實作這些方法。
資訊方法
下列方法提供 DMO 的相關信息。
- GetInputMaxLatencySetInputMaxLatency 這些方法會擷取或設定最大延遲。 範本會在衍生類別上呼叫 InternalGetInputMaxLatency 或 InternalSetInputMaxLatency。
- GetInputSizeInfoGetOutputSizeInfo。 這些方法會傳回指定數據流的 DMO 緩衝區需求。 如果未在該數據流上設定任何媒體類型,範本會傳回DMO_E_TYPE_NOT_SET。 否則,它會在衍生類別上呼叫 InternalGetInputSizeInfo 或 InternalGetOutputSizeInfo。
- GetInputStreamInfoGetOutputStreamInfo。 這些方法會傳回各種旗標,指出客戶端應該如何格式化數據。 範本會在衍生類別上呼叫 InternalGetInputStreamInfo 或 InternalGetOutputStreamInfo。
- GetStreamCount。 這個方法會傳回輸入和輸出數據流的數目。 範本會使用範本參數來實作這個方法。
資源配置的方法
- AllocateStreamingResources 方法會在串流開始之前配置 DMO 所需的任何資源。 FreeStreamingResources 方法會釋放相同的資源。 範本會分別呼叫 的 InternalAllocateStreamingResources 和 的 InternalFreeStreamingResources。
DMO 的用戶端不需要呼叫這些方法,但範本會在串流開始之前自動呼叫 AllocateStreamingResources。 因此,DMO 可以假設在呼叫 ProcessInput 時,資源已正確配置。 DMO 應在其解構函式中呼叫 FreeStreamingResources。
此外,當範本呼叫 InternalAllocateStreamingResources時,它會設定內部旗標,使其在呼叫 InternalFreeStreamingResources之前,不會再次呼叫該方法。 這可確保資源不會意外重新配置,這可能會導致記憶體流失。
串流的方式
下列方法可用來串流數據:
- GetInputStatus。 這個方法指出 DMO 目前是否可以接受輸入。 範本會在衍生類別上呼叫 InternalAcceptingInput。 如果 DMO 可以接受輸入,衍生類別會傳回S_OK,而範本會在 dwFlags 參數中設定DMO_INPUT_STATUSF_ACCEPT_DATA位。 否則,衍生類別會傳回S_FALSE,而範本會將 dwFlags 設定為零。
- ProcessInput。 此方法會處理輸入緩衝區。 此範本呼叫 AllocateStreamingResources,詳情如前所述。 然後它會在衍生類別上呼叫 InternalAcceptingInput。 如果 DMO 可以接受新的輸入,樣本會呼叫 InternalProcessInput。
- ProcessOutput。 此方法會處理一組輸出緩衝區,每個輸出數據流各一個緩衝區。 範本會呼叫 AllocateStreamingResources,然後 InternalProcessOutput。
- 不連續性。 此方法會發出輸入數據流中的不連續訊號。 範本會在衍生類別上呼叫 InternalAcceptingInput。 如果該方法傳回S_OK,範本會在衍生類別上呼叫 InternalDiscontinuity。
- Flush。 這個方法會排清 DMO。 範本會在衍生類別上呼叫 InternalFlush。 DMO 應該捨棄尚未處理完成的輸入緩衝區。
此範本不提供對 IMediaObjectInPlace 介面的任何直接支援。
鎖定方法
鎖定是用來保護多線程環境中的 DMO 狀態。 在ATL專案中,IMediaObject::Lock 方法會導致與ATL Lock 方法發生名稱衝突。 為了解決衝突,範本會將 IMediaObject 方法重新命名為 DMOLock。 當您編譯衍生類別時,請先定義 FIX_LOCK_NAME,再包含標頭檔案 Dmo.h:
#define FIX_LOCK_NAME
#include <dmo.h>
這個指示詞會使預處理器在宣告 IMediaObject 介面時,用 DMOLock 取代 Lock。 應用程式仍然可以使用 Lock名稱叫用 方法,因為 vtable 順序不會變更。 DMOLock 方法會呼叫衍生類別上 Lock 或 Unlock。 如果您使用 ATL 來實作衍生類別,這些方法已由 ATL 定義,因此不需要額外的程式代碼。 如果您未使用 ATL,則必須在衍生類別中提供 Lock 和 Unlock 方法。
範本會自動鎖定每個 IMediaObject 方法中的 DMO。 衍生類別可能需要鎖定它實作的其他公用方法內的 DMO(例如,如果它支援 IMediaObjectInPlace)。 類別範本也提供內部協助程序類別,IMediaObjectImpl::LockIt,這對鎖定和解除鎖定 DMO 很有用。
摘要
針對下列 IMediaObject 方法,範本會呼叫具有衍生類別上相同簽章的對應方法。 衍生類別必須實作第二個數據行中顯示的每個方法。
IMediaObject 方法 | 衍生類別方法 |
---|---|
分配串流資源 | 如果需要翻譯並且不涉及占位符或專業術語,可翻譯為:內部分配串流資源 |
不連貫 | 內部不連續性 |
沖洗 | 內部刷新 |
免費串流資源 | InternalFreeStreamingResources (內部免費串流資源) |
GetInputMaxLatency | InternalGetInputMaxLatency |
GetInputSizeInfo | InternalGetInputSizeInfo |
GetInputStreamInfo | InternalGetInputStreamInfo |
GetInputType | InternalGetInputType |
GetOutputSizeInfo | InternalGetOutputSizeInfo |
GetOutputStreamInfo | InternalGetOutputStreamInfo |
GetOutputType | InternalGetOutputType |
ProcessInput | InternalProcessInput |
ProcessOutput | InternalProcessOutput |
SetInputMaxLatency | InternalSetInputMaxLatency |
對於其餘 IMediaObject 方法,範本方法和衍生類別方法之間沒有一對一的對應。 下表摘要說明範本完全實作哪些方法,以及哪些方法在衍生類別上呼叫其他方法。
IMediaObject 方法 | 衍生類別方法 |
---|---|
GetInputCurrentType | 完全實施 |
GetOutputCurrentType | 完全實施 |
GetStreamCount | 完全實施 |
GetInputStatus | InternalAcceptingInput |
鎖定 (實作為 DMOLock) | 鎖定、解除鎖定 |
SetInputType | InternalCheckInputType |
SetOutputType | InternalCheckOutputType |
相關主題