カスタム ファイル タイプの登録

ここでは、フィルタ グラフ マネージャがファイル名を指定してどのようにソース フィルタを見つけるかについて説明する。この機構を使い、独自のカスタム ファイル タイプを登録できる。ファイル タイプが登録されると、アプリケーションが IGraphBuilder::RenderFile または IGraphBuilder::AddSourceFilter を呼び出すたびに、DirectShow は正しいソース フィルタを自動的にロードする。

特定のファイル名からソース フィルタを見つけるため、フィルタ グラフ マネージャは次の処理を順に行う。

  1. 同じプロトコルを探す (存在する場合)。
  2. 同じファイル拡張子を探す。
  3. "チェック バイト" と呼ばれるファイル内のバイトの同じパターンを探す。

プロトコル

ftphttp などのプロトコル名は、次のような構造を持つ HKEY_CLASSES_ROOT キーの下に登録されている。

  HKEY_CLASSES_ROOT
    <protocol>
        Source Filter = <Source filter CLSID>
        Extensions
            <.ext1> = <Source filter CLSID>
            <.ext2> = <Source filter CLSID>

ファイル名にコロン (':') がある場合、フィルタ グラフ マネージャは ':' の前の部分をプロトコル名として使用しようとする。たとえば、名前が "myprot://myfile.ext" である場合、myprot という名前のレジストリ キーを検索する。このキーが存在し、Extensions という名前のサブキーが含まれている場合、フィルタ グラフ マネージャはそのサブキー内でファイル拡張子に一致するエントリを検索する。キーの値は文字列形式の GUID でなければならない。たとえば、"{00000000-0000-0000-0000-000000000000}" である。フィルタ グラフ マネージャが Extensions サブキー内で何も見つけられない場合は、Source Filter という名前のサブキーを検索する。この値も文字列形式の GUID でなければならない。

フィルタ グラフ マネージャが一致する GUID を見つけた場合は、この値をソース フィルタの CLSID として使い、フィルタのロードを試みる。一致する値が見つからない場合は、ファイル ソース (URL) フィルタを使う。このフィルタはファイル名を URL として扱う。

このアルゴリズムには 2 つの例外がある。

  • ドライブ文字を除外するため、1 文字の文字列はプロトコルと見なさない。
  • 文字列が "file:" か "file://" である場合、プロトコルと見なさない。

ファイル拡張子

ファイル名にプロトコルがない場合、フィルタ グラフ マネージャはレジストリでキー HKEY_CLASSES_ROOT\Media Type\Extensions\.ext\ を持つエントリを探す。.ext はファイル拡張子である。このキーがある場合、値 Source Filter にはソース フィルタの CLSID が文字列形式で入っている。キーは、メジャー タイプとサブタイプの GUID を示す Media Type および Subtype の値が入っていることもある。

チェック バイト

一部のファイル タイプは、ファイル内の特定のバイト オフセットで生じるビットの特定パターンにより識別できる。フィルタ グラフ マネージャはレジストリで次の形式を持つキーを探す。

HKEY_CLASSES_ROOT\MediaType\{major type}\{subtype}

ここで major typesubtype は、バイト ストリームのメディア タイプを定義する GUID である。各キーは、12 ... のように名前が付いた 1 つ以上のサブキーがある。この値はチェック バイトを定義する。また、Source Filter という名前のサブキーがあり、ソース フィルタの CLSID を文字列形式で指定する。チェック バイト サブキーは、次のような 4 つの値の組が 1 つ以上入った文字列である。

offset**,cb,mask,**val

一致するファイルを探すため、フィルタ グラフ マネージャはバイト番号 offset からの cb バイトを読み取る。次に、mask の値に対してビットごとの AND を実行する。結果が val に等しい場合、ファイルはその 4 つの値の組の値に一致する。値 maskval は 16 進数で示される。mask エントリが空である場合、長さ cb の 1 の文字列として扱われる。offset が負の値である場合は、ファイルの最後からのオフセットを示す。キーに一致させるためには、ファイルはすべてのサブキーにあるすべての 4 つの値の組に一致する必要がある。

たとえば、レジストリで HKCR\Media Type の下に次のキーがあると想定する。

{e436eb83-524f-11ce-9f53-0020af0ba770}
    {7364696D-0000-0010-8000-00AA00389B71}
        0                    "0,4,,52494646,8,4,,524D4944"
        1                    "0,4,,4D546864"
        Source Filter        "{E436EBB5-524F-11CE-9F53-0020AF0BA770}"

最初のキーはメジャー タイプ MEDIATYPE_Stream に対応する。その下のサブキーはサブタイプ MEDIATYPE_Midi に対応する。Source Filter サブキーの値は、ファイル ソース (非同期) フィルタの CLSID を示す CLSID_AsyncReader である。

各エントリは複数の 4 つの値の組を持てる。それらすべてが一致する必要がある。次の例では、ファイルの最初の 4 バイトは 0xAB、0xCD、0x12、0x34 でなければならない。また、ファイルの最後の 4 バイトは 0xAB、0xAB、0x00、0xAB でなければならない。

    0, 4, , ABCD1234,  -4, 4, , ABAB00AB 

また、1 つのメディア タイプの下に複数のエントリが示されることもある。その場合、いずれか 1 つに一致すれば十分である。この方式では、代替マスクのセットを使える。たとえば、RIFF ヘッダーがあったりなかったりする .wav ファイルである。

 : この方式は Microsoft® Win32® の GetClassFile 関数で使われるものに似ている。

ソース フィルタのロード

フィルタ グラフ マネージャがファイルに一致するソース フィルタを見つけたと想定すると、グラフにそのフィルタを追加し、フィルタに IFileSourceFilter インターフェイスを問い合わせ、IFileSourceFilter::Load を呼び出す。Load メソッドの引数は、レジストリから決められたように、ファイル名とメディア タイプである。

フィルタ グラフ マネージャがレジストリで何も見つけられない場合、デフォルトで非同期ファイル ソース フィルタを使う。その場合、メディア タイプをMEDIATYPE_Stream、MEDIASUBTYPE_None に設定する。