DMO クラス テンプレートの使用
[このページに関連付けられている機能 DirectShow は、従来の機能です。 MediaPlayer、IMFMediaEngine、および Media Foundation のオーディオ/ビデオ キャプチャに置き換わりました。 これらの機能は、Windows 10とWindows 11用に最適化されています。 新しいコードでは、可能であれば、DirectShow ではなく Media Foundation で MediaPlayer、IMFMediaEngine、Audio/Video Capture を使用することを強くお勧めします。 Microsoft は、従来の API を使用する既存のコードを、可能であれば新しい API を使用するように書き直すよう提案しています。]
DirectShow には、DMU を実装するためのクラス テンプレート IMediaObjectImpl が含まれています。 テンプレートは、入力パラメーターの検証など、多くの "簿記" タスクを処理します。 テンプレートを使用すると、DMO に固有の機能に集中できます。 さらに、このテンプレートは、堅牢な実装を確実に作成するのに役立ちます。 テンプレートは、SDK の Include ディレクトリにあるヘッダー ファイル Dmoimpl.h で定義されています。
IMediaObjectImpl テンプレートは、IMediaObject インターフェイスを継承します。 テンプレートを使用して DMO を作成するには、 IMediaObjectImpl から派生する新しいクラスを定義します。 このテンプレートは、すべての IMediaObject メソッドを実装します。 ほとんどの場合、テンプレートは派生クラスで対応するプライベート メソッドを呼び出します。 このテンプレートには、次の機能があります。
- 基本的なパラメーター チェック。 テンプレート メソッドは、必要なパラメーターが NULL ではないこと、ストリーム インデックスが範囲内であること、およびフラグが有効であることを確認します。
- ロック。 テンプレート メソッドは、 Lock と Unlock という 2 つの内部メソッドを呼び出して、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
3 つのテンプレート パラメーターは、_DERIVED_、NUMBEROFINPUTS、および NUMBEROFOUTPUTS です。 _DERIVED_ をクラスの名前と同じに設定します。 他の 2 つのパラメーターは、DMO 上の入力ストリームと出力ストリームの数を定義します。 たとえば、1 つの入力ストリームと 2 つの出力ストリームをサポートする 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 を 0 に設定します。
- ProcessInput。 このメソッドは、入力バッファーを処理します。 このテンプレートは、前に説明した AllocateStreamingResources を呼び出します。 次に、派生クラスで InternalAcceptingInput を呼び出します。 DMO が新しい入力を受け入れられる場合、テンプレートは InternalProcessInput を呼び出します。
- ProcessOutput。 このメソッドは、出力ストリームごとに 1 つのバッファーである出力バッファーのセットを処理します。 テンプレートは AllocateStreamingResources を呼び出し、 InternalProcessOutput を呼び出します。
- 不連続性。 このメソッドは、入力ストリームの不連続性を通知します。 テンプレートは、派生クラスで InternalAcceptingInput を呼び出します。 そのメソッドがS_OKを返す場合、テンプレートは派生クラスで InternalDiscontinuity を呼び出します。
- Flush。 このメソッドは DMO をフラッシュします。 テンプレートは、派生クラスで InternalFlush を呼び出します。 DMO は、処理対象として保持されている入力バッファーをすべて破棄する必要があります。
このテンプレートでは、 IMediaObjectInPlace インターフェイスの直接サポートは提供されません。
ロックのメソッド
ロックは、マルチスレッド環境での DMO の状態を保護するために使用されます。 ATL プロジェクトでは、 IMediaObject::Lock メソッドは ATL Lock メソッドと名前の競合を引き起こします。 競合を解決するために、テンプレートは IMediaObject メソッドの名前を DMOLock に変更します。 派生クラスをコンパイルするときは、ヘッダー ファイル Dmo.h を含FIX_LOCK_NAME前に定義します。
#define FIX_LOCK_NAME
#include <dmo.h>
このディレクティブにより、プリプロセッサは IMediaObject インターフェイスの宣言で DMOLock を Lock に置き換えます。 vtable の順序は変更されないため、アプリケーションは Lock という名前を使用してメソッドを呼び出すことができます。 DMOLock メソッドは、派生クラスの Lock または Unlock を呼び出します。 ATL を使用して派生クラスを実装する場合、これらのメソッドは ATL によって既に定義されているため、追加のコードは必要ありません。 ATL を使用していない場合は、派生クラスに Lock メソッドと Unlock メソッドを指定する必要があります。
テンプレートは、各 IMediaObject メソッドの DMO を自動的にロックします。 派生クラスは、実装する他のパブリック メソッド (たとえば、 IMediaObjectInPlace をサポートしている場合) 内で DMO をロックする必要がある場合があります。 クラス テンプレートには、内部ヘルパー クラス IMediaObjectImpl::LockIt も用意されています。これは、DMO のロックとロック解除に役立ちます。
まとめ
次の IMediaObject メソッドの場合、テンプレートは、派生クラスで同じシグネチャを持つ対応するメソッドを呼び出します。 派生クラスは、2 番目の列に示されている各メソッドを実装する必要があります。
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 メソッドでは、テンプレート メソッドと派生クラス メソッドの間に 1 対 1 の対応はありません。 次の表は、テンプレートによって完全に実装されるメソッドと、派生クラスで他のメソッドを呼び出すメソッドをまとめたものです。
IMediaObject メソッド | 派生クラス メソッド |
---|---|
GetInputCurrentType | 完全に実装 |
GetOutputCurrentType | 完全に実装 |
GetStreamCount | 完全に実装 |
GetInputStatus | InternalAcceptingInput |
Lock ( DMOLock として実装) | ロック、 ロック解除 |
SetInputType | InternalCheckInputType |
SetOutputType | InternalCheckOutputType |
関連トピック