使用 DMO 類別範本
[與此頁面相關的功能 DirectShow是舊版功能。 它已被 MediaPlayer、 IMFMediaEngine和 Media Foundation 中的音訊/視訊擷取取代。 這些功能已針對Windows 10和Windows 11進行優化。 Microsoft 強烈建議新程式碼盡可能使用 MediaPlayer、 IMFMediaEngine 和 音訊/視訊擷取 ,而不是 DirectShow。 Microsoft 建議使用舊版 API 的現有程式碼盡可能重寫為使用新的 API。
DirectShow 包含實作 DMO 的類別範本 IMediaObjectImpl。 範本會處理許多「記事」工作,例如驗證輸入參數。 藉由使用範本,您可以專注于 DMO 特有的功能。 此外,範本也有助於確保您建立健全的實作。 範本定義于標頭檔 Dmoimpl.h 中,位於 SDK 的 Include 目錄中。
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 上設定或擷取媒體類型:
- GetInputType、 GetOutputType。 這些方法會依資料流程編號和類型索引傳回慣用的媒體類型。 範本會在衍生類別上呼叫 InternalGetInputType 或 InternalGetOutputType 。
- SetInputType、 SetOutputType。 這些方法會在資料流程上設定媒體類型、測試媒體類型,或清除媒體類型。 若要驗證媒體類型,範本會在衍生類別上呼叫 InternalCheckInputType 或 InternalCheckOutputType 。 衍生類別會傳回S_OK,以接受類型或DMO_E_INVALIDTYPE來拒絕類型。 範本會處理設定或清除媒體類型。
- GetInputCurrentType、 GetOutputCurrentType。 這些方法會傳回資料流程的目前媒體類型,如果沒有設定類型,DMO_E_TYPE_NOT_SET。 此範本會完全實作這些方法。
資訊方法
下列方法提供 DMO 的相關資訊。
- GetInputMaxLatency、 SetInputMaxLatency。 這些方法會擷取或設定最大延遲。 範本會在衍生類別上呼叫 InternalGetInputMaxLatency 或 InternalSetInputMaxLatency 。
- GetInputSizeInfo、 GetOutputSizeInfo。 這些方法會傳回指定資料流程的 DMO 緩衝區需求。 如果該資料流程上未設定媒體類型,範本會傳回DMO_E_TYPE_NOT_SET。 否則,它會在衍生類別上呼叫 InternalGetInputSizeInfo 或 InternalGetOutputSizeInfo 。
- GetInputStreamInfo、 GetOutputStreamInfo。 這些方法會傳回各種旗標,指出用戶端應該如何格式化資料。 範本會在衍生類別上呼叫 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 。
- 排清。 這個方法會排清 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。 如果衍生類別支援 IMediaObjectInPlace) ,則可能需要鎖定它實作的其他公用方法內的 DMO (。 類別範本也提供內部協助程式類別 IMediaObjectImpl::LockIt,這適用于鎖定和解除鎖定 DMO。
總結
針對下列 IMediaObject 方法,範本會呼叫在衍生類別上具有相同簽章的對應方法。 衍生類別必須實作第二個數據行中顯示的每個方法。
IMediaObject 方法 | 衍生類別方法 |
---|---|
AllocateStreamingResources | InternalAllocateStreamingResources |
間斷 | InternalDiscontinuity |
清除 | InternalFlush |
FreeStreamingResources | 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 |
相關主題