カスタム ファイル タイプの登録
ここでは、フィルタ グラフ マネージャがファイル名を指定してどのようにソース フィルタを見つけるかについて説明する。この機構を使い、独自のカスタム ファイル タイプを登録できる。ファイル タイプが登録されると、アプリケーションが IGraphBuilder::RenderFile または IGraphBuilder::AddSourceFilter を呼び出すたびに、DirectShow は正しいソース フィルタを自動的にロードする。
特定のファイル名からソース フィルタを見つけるため、フィルタ グラフ マネージャは次の処理を順に行う。
- 同じプロトコルを探す (存在する場合)。
- 同じファイル拡張子を探す。
- "チェック バイト" と呼ばれるファイル内のバイトの同じパターンを探す。
プロトコル
ftp、http などのプロトコル名は、次のような構造を持つ 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 type と subtype は、バイト ストリームのメディア タイプを定義する GUID である。各キーは、1、2 ... のように名前が付いた 1 つ以上のサブキーがある。この値はチェック バイトを定義する。また、Source Filter という名前のサブキーがあり、ソース フィルタの CLSID を文字列形式で指定する。チェック バイト サブキーは、次のような 4 つの値の組が 1 つ以上入った文字列である。
offset**,cb,mask,**val
一致するファイルを探すため、フィルタ グラフ マネージャはバイト番号 offset からの cb バイトを読み取る。次に、mask の値に対してビットごとの AND を実行する。結果が val に等しい場合、ファイルはその 4 つの値の組の値に一致する。値 mask と val は 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 に設定する。