Microsoft DirectX 8.0 |
このトピックでは、変換フィルタの作成用に提供されているクラスについて説明する。「変換フィルタの作成」で変換フィルタ作成の具体的な手順を見る前に、このトピックの情報を背景知識として理解する必要がある。
このトピックは、以下のセクションを含んでいる。
変換フィルタを開発するうえで最も簡単な方法は、変換フィルタ クラスを使用することである。これらのクラスは、ほとんどの種類の変換フィルタで機能する。通常、非コピーの変換フィルタは CTransInPlaceFilter クラスとその関連ピン クラスから派生する。コピー変換フィルタは、CTransformFilter クラスとその関連ピン クラスから派生する。
変換フィルタ クラスは階層的であり、階層ツリーの最下位には変換インプレイス クラスが位置する。次の図に示すように、CTransInPlaceFilter は CTransformFilter から派生し、CTransformFilter は CBaseFilter から派生する。
次の図に示すように、CTransInPlaceInputPin クラスは CTransformInputPin クラスから派生し、CTransformInputPin クラスは CBaseInputPin クラスから派生する。
次の図に示すように、CTransInPlaceOutputPin クラスは CTransformOutputPin クラスから派生し、CTransformOutputPin クラスは CBaseOutputPin クラスから派生する。
コピー変換クラスと変換インプレイス クラスでは、多くの機能が共通している。これは、変換インプレイス クラスのメンバ関数がほとんどすべてコピー変換クラスから派生するためである。基底クラスに対する変換クラスの主な拡張内容は、すべての必要なピン メンバ関数が実装されていることである。したがって、デフォルトの実装では、メインのフィルタ クラスを (CTransInPlaceFilter または CTransformFilterから) 派生するだけでよい。
派生されたフィルタ クラスは、いくつかのメンバ関数を提供する必要がある。これは一般に次のような目的のためである
すべての派生されたフィルタ クラスは、スタティックな CFactoryTemplate::CreateInstance 関数を実装しなければならない。また、CBaseFilter::GetSetupData メンバ関数をオーバーライドしてフィルタを自己登録にすることもできる。それとは別に、クラスは変換基底クラス内のいくつかのメンバ関数をオーバーライドする必要がある。フィルタのインスタンス化の詳細については、「変換フィルタの作成」を参照すること。
派生されたフィルタ クラスが CTransformFilter クラスに基づいている場合、以下のメンバ関数をオーバーライドする必要がある。
Transform | 変換を実装する。 |
CheckInputType | メディア タイプのサポートを確認する。 |
CheckTransform | このタイプの変換のサポートを確認する (デバッグ用ビルドのみ)。 |
DecideBufferSize | コピー時のサイズと数を設定する。 |
GetMediaType | 出力ピンのメディア タイプを指定する。 |
派生されたフィルタ クラスが CTransInPlaceFilter クラスに基づいている場合、以下のメンバ関数をオーバーライドする必要がある。
Transform | 変換を実装する。 |
CheckInputType | メディア タイプのサポートを確認する。 |
最低限のオーバーライドによって変換フィルタにデフォルトの実装を提供する以外に、他のメンバ関数をオーバーライドして動作をさらに特化することもできる。もちろん、どのメンバ関数をオーバーライドするかは、フィルタに求める機能によって異なる。たとえば、フィルタに複数の入力ピンと出力ピンを持たせたい場合は、GetPin および GetPinCount メンバ関数をオーバーライドする必要がある。
また、BreakConnect や CompleteConnect などいくつかの基底クラス メンバ関数は、ピンを通したフィルタへの通知として呼び出される。一般に、そのようなメンバ関数のほとんどは、ピンにだけ存在する。CTransformFilter に基づくクラスでは、ピン関数はフィルタ クラス内の似た名前の関数を呼び出すように実装されている。これは、オーバーライドの必要性が高いメンバ関数はすべて 1 つのフィルタ クラスに集められていることを意味する。そのため、ピン クラスを変更しないで済み、実装が小さく簡単になる。これらのメンバ関数を以下に示す。
メンバ関数 | オーバーライドする理由 |
---|---|
NonDelegatingQueryInterface | 派生クラスに追加されたインターフェイスを配布するため |
GetPinCount | 変換フィルタにピンを追加する場合 |
GetPin | 変換フィルタにピンを追加する場合 |
CheckConnect | 接続時に追加インターフェイスを取得するため、など |
BreakConnect | 接続の切断時に追加インターフェイスを解放するため、など |
CompleteConnect | 接続の終了時にいくつかの動作を実行するため (入力ピンの再接続など) |
SetMediaType | メディア タイプが設定されたときに通知を受けるため |
StartStreaming | ストリーミング状態に入るときに通知を受けるため |
StopStreaming | ストリーミング状態を出るときに通知を受けるため |
AlterQuality | 品質コントロール メッセージを単に渡す以外に何らかの操作を行うため |
このサンプルは、完全な最小機能フィルタを示している。これは、フィルタに対して必要な最低限の実装を示すほかには、何もしない。このフィルタは変換インプレイス クラスを使用し、そのフィルタ クラスを CTransInPlaceFilter クラスから派生している。派生されたフィルタ クラス CNullNull のクラス宣言を次に示す。
// CNullNull // class CNullNull : public CTransInPlaceFilter { public: static CUnknown *CreateInstance(LPUNKNOWN punk, HRESULT *phr); DECLARE_IUNKNOWN; LPAMOVIESETUP_FILTER GetSetupData() { return &sudNullNull; } private: // コンストラクタ。単に基底クラス コンストラクタを呼び出す。 CNullNull(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr) : CTransInPlaceFilter (tszName, punk, CLSID_NullNull, phr) { } // CTransInPlaceFilter 基底クラスの純粋仮想変換をオーバーライドする。 // 変換の "実際の仕事" は *pSample を変更することで行われる。 // Null 変換は *pSample を変更しない。 HRESULT Transform(IMediaSample *pSample){ return NOERROR; } // このフィルタはすべての入力タイプを受け入れる。 // (通常は、受け入れないタイプに対して S_FALSE を返す) HRESULT CheckInputType(const CMediaType* mtIn) { return S_OK; } };
この例には、基底クラスで必要な、以下の基本的なメンバ関数が示されている。
CreateInstance | クラスを COM オブジェクトとしてインスタンス化するために、すべてのクラスで必要。 |
GetSetupData | CBaseFilter::GetSetupData をオーバーライドし、この特定のフィルタを登録するために必要な情報をクラスに提供する。ここでは、SDK に含まれる Nullnull.cpp ファイルに定義された構造体のアドレスを提供している。 |
CNullNull | クラス コンストラクタ。通常は単に基底クラス コンストラクタを呼び出す。 |
Transform | CTransInPlaceFilter::Transform をオーバーライドし、CNullNull の主たる作業を実行する。ここでは、何もしない。 |
CheckInputType | CTransInPlaceFilter::CheckInputType をオーバーライドし、接続時のメディア タイプを確認する。この関数は単にメディア タイプを次のフィルタに渡すだけなので、ここではすべてのメディア タイプを受け入れる。 |
厳密に言えば、GetSetupData はフィルタを自己登録にしたい場合にのみ必要である。しかし、この機能は基底クラスで実装され、実装は簡単に行えるので、これを基底クラスに含めておくことをお勧めする。