圧縮フィルタの選択
次に示すように、ビデオまたはオーディオの圧縮を実行できるソフトウェア コンポーネントは数種類ある。
- ネイティブ DirectShow フィルタ
- ビデオ圧縮マネージャ (VCM) CODEC
- オーディオ圧縮マネージャ (ACM) CODEC
- DirectX Media Object(DMO)
DirectShow では、VCM CODEC は AVI コンプレッサ フィルタによってラップされており、ACM CODEC は ACM ラッパー フィルタによってラップされている。DMO は、DMO ラッパー フィルタによってラップされている。System Device Enumerator が提供する、これらのコンプレッサ タイプを列挙したり作成したりする方法は一貫性があり、基盤となるモデルについて心配する必要はない。
System Device Enumerator の詳細については、「System Device Enumerator の使い方」を参照すること。簡単に説明すると、すべての DirectShow フィルタはカテゴリ別に分類され、各カテゴリは GUID で識別される。ビデオ コンプレッサの場合、カテゴリ GUID は CLSID_VideoCompressorCategory である。オーディオ コンプレッサの場合は、CLSID_AudioCompressorCategory である。System Device Enumerator は、特定のカテゴリを列挙するために、IEnumMoniker インターフェイスをサポートする "列挙子オブジェクト" を作成する。アプリケーションはこのインターフェイスを使って、デバイス モニカを取得する。各デバイス モニカは、DirectShow フィルタのインスタンスを表す。モニカを使ってフィルタを作成するか、または、フィルタを作成しないでデバイスのフレンドリ名を取得する。
ユーザーのシステムで利用可能なビデオ コンプレッサまたはオーディオ コンプレッサを列挙するには、次の作業を行う。
- CoCreateInstance を呼び出して、クラス ID が CLSID_SystemDeviceEnum の System Device Enumerator を作成する。
- フィルタ カテゴリ GUID を指定して ICreateDevEnum::CreateClassEnumerator を呼び出す。このメソッドは、IEnumMoniker インターフェイス ポインタを返す。
- IEnumMoniker::Next メソッドを使って、デバイス モニカを列挙する。このメソッドは、モニカを表す IMoniker インターフェイスを返す。
モニカからフレンドリ名を取得するには、次の作業を行う。
- IMoniker::BindToStorage メソッドを呼び出す。このメソッドは、IPropertyBag インターフェイス ポインタを返す。
- IPropertyBag::Read メソッドを使って、FriendlyName プロパティを読み取る。
通常、アプリケーションはコンプレッサの一覧を表示するので、ユーザーはその一覧の中から選択できる。たとえば、次のコードは利用できるビデオ コンプレッサの名前をリスト ボックスに設定する。
void OnInitDialog(HWND hDlg)
{
HRESULT hr;
ICreateDevEnum *pSysDevEnum = NULL;
IEnumMoniker *pEnum = NULL;
IMoniker *pMoniker = NULL;
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
(void**)&pSysDevEnum);
if (FAILED(hr))
{
// エラーを処理する。
}
hr = pSysDevEnum->CreateClassEnumerator(
CLSID_VideoCompressorCategory, &pEnum, 0);
if (hr == S_OK) // S_FALSE はこのカテゴリでは何も意味しない。
{
while (S_OK == pEnum->Next(1, &pMoniker, NULL))
{
IPropertyBag *pPropBag = NULL;
pMoniker->BindToStorage(0, 0, IID_IPropertyBag,
(void **)&pPropBag);
VARIANT var;
VariantInit(&var);
hr = pPropBag->Read(L"FriendlyName", &var, 0);
if (SUCCEEDED(hr))
{
LRESULT iSel = AddString(GetDlgItem(hDlg,
IDC_CODEC_LIST), var.bstrVal);
}
VariantClear(&var);
pPropBag->Release();
pMoniker->Release();
}
}
SendDlgItemMessage(hDlg, IDC_CODEC_LIST,
LB_SETCURSEL, 0, 0);
pSysDevEnum->Release();
pEnum->Release();
}
モニカからフィルタ インスタンスを作成するには、IMoniker::BindToObject メソッドを呼び出す。このメソッドは、IBaseFilter ポインタを返す。
IBaseFilter *pFilter = NULL;
hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter,
(void**)&pFilter);
if (SUCCEEDED(hr))
{
// フィルタを使う。
// 忘れずに IBaseFilter インターフェイスを解放すること。
}
VCM CODEC の場合、すべての CODEC は同じ AVI 圧縮フィルタにラップされているが、各モニカは特定の CODEC を表す。BindToObject を呼び出すと、その CODEC 用に初期化された、このフィルタのインスタンスが作成される。このため、AVI 圧縮フィルタに対して CoCreateInstance を直接呼び出すことはできない。必ず System Device Enumerator を経由する必要がある。