Microsoft DirectX 8.0

DirectShow オブジェクトの登録方法

このトピックでは、Microsoft® DirectShow® フィルタを自己登録にする方法を説明する。以下のセクションで構成される。

ここでは、DLL の作成方法については説明しない。DLL 作成の詳細については、「DLL の作成方法」を参照すること。

レジストリ キーのレイアウト

DirectShow フィルタは、次の 2 つの場所に登録される。

次に、DLL のレジストリ エントリを示す。

HKEY_CLASSES_ROOT
    CLSID
        Filter CLSID
            REG_SZ: (Default) = フレンドリ名

            InprocServer32
                REG_SZ: (Default) = DLL のファイル名
                REG_SZ: ThreadingModel = Both

次に、フィルタ情報のレジストリ エントリを示す。

HKEY_CLASSES_ROOT
    CLSID
        Category
            Instance
                Filter CLSID
                    REG_SZ: CLSID = フィルタの CLSID
                    REG_BINARY: Filter Data = フィルタ情報
                    REG_SZ: FriendlyName = フレンドリ名

"Category" は、フィルタ カテゴリの GUID である。フィルタ情報はバイナリ フォーマットにパックされる。IFilterMapper2 インターフェイスが、フィルタのレジストリを検索するときに、このデータをアンパックする。

フィルタの登録

フィルタを登録するには、次の操作を行う。

  1. フィルタ情報を宣言する。
  2. フィルタのファクトリ テンプレートに、フィルタ情報へのポインタを含める。
  3. DllRegisterServer 関数を実装する。

以下では、これらの操作について詳しく説明する。

フィルタ情報の宣言

最初のステップは、フィルタ情報の宣言である。DirectShow は、フィルタ、ピン、およびメディア タイプを記述するために、次のような構造体を定義している。

AMOVIESETUP_FILTERフィルタを記述する。
AMOVIESETUP_PINピンを記述する。
AMOVIESETUP_MEDIATYPEメディア タイプを記述する。

これらの構造体はネストしている。フィルタ構造体は ピン構造体の配列へのポインタを持ち、それぞれのピン構造体は、メディア タイプ構造体の配列へのポインタを持っている。これらの構造体によって、IFilterMapper2 インターフェイスがフィルタを見つけるために必要な情報が十分に与えられる。構造体によって、フィルタが完全に記述されるわけではない。たとえば、フィルタが同じピンの複数のインスタンスを生成する場合でも、そのフィルタに対して 1 つの AMOVIESETUP_PIN 構造体を宣言するだけでよい。また、フィルタは、登録するメディア タイプのすべての組み合わせをサポートするように求められてはいない。

このセットアップ構造体を、DLL の内部でグローバル変数として宣言する。次の例に、出力ピンを 1 つ持つフィルタを示す。

static const WCHAR g_wszName[] = L"Some Filter";

AMOVIESETUP_MEDIATYPE sudMediaTypes[] = {
    { &MEDIATYPE_Video, &MEDIASUBTYPE_RGB24 },
    { &MEDIATYPE_Video, &MEDIASUBTYPE_RGB32 },
};

AMOVIESETUP_PIN sudOutputPin = {
    L"",            // 現在は使用されていない。
    FALSE,          // このピンをレンダリングするか?
    TRUE,           // これは出力ピンか?
    FALSE,          // このフィルタはゼロ インスタンスを生成できるか?
    FALSE,          // このフィルタは複数のインスタンスを生成するか?
    &GUID_NULL,     // 現在は使用されていない。
    NULL,           // 現在は使用されていない。
    2,              // メディア タイプの数。
    sudMediaTypes   // メディア タイプへのポインタ。
};

AMOVIESETUP_FILTER sudFilterReg = {
    &CLSID_SomeFilter,      // フィルタの CLSID
    g_wszName,              // フィルタの名前
    MERIT_NORMAL,           // メリット
    1,                      // ピン タイプの数
    &sudPins                // ピン情報へのポインタ
};

フィルタ名はほかの場所でも使用するので、静的グローバル変数としてフィルタ名を宣言している。

ファクトリ テンプレートの宣言

次のステップは、フィルタ用のファクトリ テンプレートの宣言である。ファクトリ テンプレートは、クラス ファクトリの情報を格納する C++ クラスである。DLL の中で、DLL 内のフィルタまたは COM コンポーネントごとに 1 つずつ、ファクトリ テンプレートのグローバル配列を宣言する。この配列の名前は g_Templates でなければならない。ファクトリ テンプレートの詳細については、「DLL の作成方法」を参照すること。

ファクトリ テンプレートの m_pAMovieSetup_Filter メンバは、前に説明した AMOVIESETUP_FILTER 構造体へのポインタである。次の例に、ファクトリ テンプレートを示す。前の例で示した構造体を使用している。

CFactoryTemplate g_Templates[] =
{
    {
        g_wszName,                      // 名前
        &CLSID_SomeFilter,              // CLSID
        CSomeFilter::CreateInstance,    // 作成関数
        NULL,
        &sudFilterReg                   // フィルタ情報へのポインタ
    }
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);

DllRegisterServer の実装

最後のステップは、DllRegisterServer 関数の実装である。コンポーネントが含まれた DLL は、この関数を公開しなければならない。この関数は、セットアップ プログラム、またはユーザーが Regsvr32.exe ツールを実行したときに呼び出される。

次の例に、DlLRegisterServer の最小限の実装を示す。

STDAPI DllRegisterServer(void)
{
    return AMovieDllRegisterServer2(TRUE);
}

DirectShow 関数である AMovieDllRegisterServer2 は、g_Templates 配列のすべてのコンポーネント用にレジストリのエントリを作成する。ただし、この関数には制限がいくつかある。まず、この関数はすべてのフィルタを CLSID_LegacyAmFilterCategory カテゴリに割り当てるが、すべてのフィルタがこのカテゴリに属するわけではない。たとえば、キャプチャ フィルタや圧縮フィルタは、それぞれのカテゴリを持っている。カテゴリ一覧については、「フィルタ カテゴリ」を参照すること。次に、フィルタがハードウェア デバイスをサポートしている場合は、AMovieDLLRegisterServer2 が処理しない 2 つの情報、つまり "メディア" と "ピン カテゴリ" を登録する必要がある。メディアは、ハードウェア デバイスの通信方法 (バスなど) を定義し、ピン カテゴリは、ピンの機能を定義する。メディアの詳細については、Microsoft® Windows® Driver Development Kit (DDK) の「KSPIN_MEDIUM」を参照すること。ピン カテゴリの一覧については、「ピン プロパティ セット」を参照すること。

フィルタ カテゴリ、メディア、またはピン カテゴリを指定する場合は、DllRegisterServer 内から IFilterMapper2::RegisterFilter メソッドを呼び出す。このメソッドは、REGFILTER2 構造体へのポインタを受け取る。REGFILTER2 構造体は、フィルタに関する情報を指定する。

面倒なのは、REGFILTER2 構造体が、ピンを登録するためのフォーマットを 2 種類サポートしていることである。dwVersion メンバで、このフォーマットを指定する。

REGFILTERPINS2 構造体には、ピン メディアとピン カテゴリのエントリが含まれる。また、一部の項目については、AMOVIESETUP_PIN がブール値として宣言するビット フラグを使用する。

次の例に、DllRegisterServer の中から IFilterMapper2::RegisterFilter を呼び出す方法を示す。

REGFILTER2 rf2FilterReg = {
    1,              // バージョン 1 (ピン メディアとピン カテゴリはなし)
    MERIT_NORMAL,   // メリット
    1,              // ピンの数
    &sudPins        // ピン情報へのポインタ
};

STDAPI DllRegisterServer(void)
{
    HRESULT hr;
    IFilterMapper2 *pFM2 = NULL;

    hr = AMovieDllRegisterServer2(TRUE);
    if (FAILED(hr))
        return hr;

    hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
            IID_IFilterMapper2, (void **)&pFM2);

    if (FAILED(hr))
        return hr;

    hr = pFM2->RegisterFilter(
        CLSID_SomeFilter,                // フィルタの CLSID
        g_wszName,                       // フィルタの名前
        NULL,                            // デバイス モニカ
        &CLSID_VideoCompressorCategory,  // ビデオ コンプレッサのカテゴリ
        g_wszName,                       // インスタンス データ
        &rf2FilterReg                    // フィルタ情報へのポインタ
    );
    pFM2->Release();
    return hr;
}

フィルタの登録解除

フィルタの登録を解除するには、DllUnregisterServer 関数を実装する。この関数の中で、値 FALSE を使って DirectShow AMovieDllRegisterServer2 関数を呼び出す。フィルタの登録時に IFilterMapper2::RegisterFilter を呼び出した場合は、ここで IFilterMapper2::UnregisterFilter メソッドを呼び出す。

次の例に、フィルタの登録を解除する方法を示す。

STDAPI DllUnregisterServer()
{
    HRESULT hr;
    IFilterMapper2 *pFM2 = NULL;

    hr = AMovieDllRegisterServer2(FALSE);
    if (FAILED(hr))
        return hr;
 
    hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
            IID_IFilterMapper2, (void **)&pFM2);

    if (FAILED(hr))
        return hr;

    hr = pFM2->UnregisterFilter(&CLSID_VideoCompressorCategory, 
            g_wszName, CLSID_SomeFilter);

    pFM2->Release();
    return hr;
}