共用方式為


使用 DMO 類別範本

[與此頁面相關的功能 DirectShow是舊版功能。 它已被 MediaPlayerIMFMediaEngineMedia Foundation 中的音訊/視訊擷取取代。 這些功能已針對Windows 10和Windows 11進行優化。 Microsoft 強烈建議新程式碼盡可能使用 MediaPlayerIMFMediaEngine音訊/視訊擷取 ,而不是 DirectShow。 Microsoft 建議使用舊版 API 的現有程式碼盡可能重寫為使用新的 API。

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

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方法會釋放相同的資源。 範本分別呼叫 InternalAllocateStreamingResourcesInternalFreeStreamingResources

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方法會在衍生類別上呼叫LockUnlock。 如果您使用 ATL 來實作衍生類別,這些方法已經由 ATL 定義,因此不需要額外的程式碼。 如果您未使用 ATL,則必須在衍生類別中提供 LockUnlock 方法。

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

 

IMediaObjectImpl 類別範本

撰寫 DMO