共用方式為


使用 DMO 類別範本

[與此頁面相關聯的功能,DirectShow是舊版功能。 它已被 MediaPlayerIMFMediaEngine和媒體基礎結構中的音頻/視頻擷取取代。 這些功能已針對 Windows 10 和 Windows 11 進行優化。 Microsoft強烈建議新程式代碼盡可能在媒體 基礎中使用 MediaPlayerIMFMediaEngine 音訊/視訊擷取,而不是 DirectShow。 Microsoft建議使用舊版 API 的現有程式代碼,盡可能改寫成使用新的 API。]

DirectShow 包含類別範本,IMediaObjectImpl,用於實作 DMO。 範本會處理許多「記帳」工作,例如驗證輸入參數。 藉由使用範本,您可以專注於 DMO 特有的功能。 此外,範本可協助您確保建立健全的實作。 範本定義於位於 SDK Include 目錄的標頭檔 Dmoimpl.h 中。

IMediaObjectImpl 範本會繼承 IMediaObject 介面。 若要使用範本建立 DMO,請定義衍生自 IMediaObjectImpl的新類別。 此範本會實作所有 IMediaObject 方法。 在大部分情況下,範本會在衍生類別上呼叫對應的私用方法。 此樣本提供下列功能:

  • 基本參數檢查。 範本方法會確認必要的參數未 NULL、數據流索引在範圍內,且旗標有效。
  • 鎖定。 範本方法會呼叫兩個內部方法,LockUnlock,以串行化 DMO 上的作業。 這項功能可確保 DMO 執行緒安全。
  • 媒體類型。 範本會儲存用戶端所設定的媒體類型,並提供媒體類型的存取子方法。
  • 串流。 範本會防止串流處理,直到客戶端設定所有非選擇性數據流的媒體類型為止。 它也可確保在串流開始之前,先呼叫 IMediaObject::AllocateStreamingResources 方法,以確保已配置資源。

衍生類別必須實作 IUnknown 介面;範本不提供此介面。 您可以使用 Active Template Library(ATL)來實作 IUnknown,或者提供其他一些實作。 範本也不會實作鎖定機制。 衍生類別必須實作 LockUnlock 方法。 如果您使用 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。 這些方法會依數據流編號和類型索引傳回慣用的媒體類型。 範本會在衍生類別上呼叫 InternalGetInputTypeInternalGetOutputType
  • SetInputTypeSetOutputType。 這些方法會在數據流上設定媒體類型、測試媒體類型或清除媒體類型。 若要驗證媒體類型,範本會在衍生類別上呼叫 InternalCheckInputTypeInternalCheckOutputType。 衍生類別會傳回 S_OK 以接受該類型,或傳回 DMO_E_INVALIDTYPE 以拒絕該類型。 模板會處理設定或清除媒體類型。
  • GetInputCurrentTypeGetOutputCurrentType。 這些方法會傳回串流的當前媒體類型,如果沒有設定類型,則回傳 DMO_E_TYPE_NOT_SET。 範本會完全實作這些方法。

資訊方法

下列方法提供 DMO 的相關信息。

  • GetInputMaxLatencySetInputMaxLatency 這些方法會擷取或設定最大延遲。 範本會在衍生類別上呼叫 InternalGetInputMaxLatencyInternalSetInputMaxLatency
  • GetInputSizeInfoGetOutputSizeInfo。 這些方法會傳回指定數據流的 DMO 緩衝區需求。 如果未在該數據流上設定任何媒體類型,範本會傳回DMO_E_TYPE_NOT_SET。 否則,它會在衍生類別上呼叫 InternalGetInputSizeInfoInternalGetOutputSizeInfo
  • GetInputStreamInfoGetOutputStreamInfo。 這些方法會傳回各種旗標,指出客戶端應該如何格式化數據。 範本會在衍生類別上呼叫 InternalGetInputStreamInfoInternalGetOutputStreamInfo
  • 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 方法會呼叫衍生類別上 LockUnlock。 如果您使用 ATL 來實作衍生類別,這些方法已由 ATL 定義,因此不需要額外的程式代碼。 如果您未使用 ATL,則必須在衍生類別中提供 LockUnlock 方法。

範本會自動鎖定每個 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

 

IMediaObjectImpl 類別範本

撰寫 DMO