圧縮フィルターの選択
[このページに関連付けられている機能 DirectShow は、従来の機能です。 MediaPlayer、IMFMediaEngine、Media Foundation のオーディオ/ビデオ キャプチャに置き換わりました。 これらの機能は、Windows 10とWindows 11用に最適化されています。 新しいコードでは、可能であれば、DirectShow ではなく Media Foundation で MediaPlayer、IMFMediaEngine、Audio/Video Capture を使用することを強くお勧めします。 Microsoft は、レガシ API を使用する既存のコードを、可能であれば新しい API を使用するように書き換えるよう提案しています。]
次のような、いくつかの種類のソフトウェア コンポーネントでビデオまたはオーディオの圧縮を実行できます。
- ネイティブ DirectShow フィルター
- Video Compression Manager (VCM) コーデック
- Audio Compression Manager (ACM) コーデック
- DirectX メディア オブジェクト (DMU)
DirectShow では、VCM コーデックは AVI コンプレッサー フィルターによってラップされ、ACM コーデックは ACM ラッパー フィルターによってラップされます。 DMO ラッパー フィルターによって DMO がラップされます。 システム デバイス列挙子は、基になるモデルを気にすることなく、これらのコンプレッサーの種類を列挙して作成するための一貫した方法を提供します。
システム デバイス列挙子の詳細については、「 システム デバイス列挙子の使用」を参照してください。 簡単に言うと、すべての DirectShow フィルターはカテゴリ別に分類され、各カテゴリは GUID で識別されます。 ビデオ コンプレッサーの場合、カテゴリ GUID はCLSID_VideoCompressorCategory。 オーディオコンプレッサーの場合はCLSID_AudioCompressorCategory。 特定のカテゴリを列挙するために、システム デバイス列挙子は、IEnumMoniker インターフェイスをサポートする列挙子オブジェクトを作成します。 アプリケーションでは、このインターフェイスを使用してデバイス モニカーを取得します。各デバイス モニカーは DirectShow フィルターのインスタンスを表します。 モニカーを使用してフィルターを作成したり、フィルターを作成せずにデバイスのフレンドリ名を取得したりできます。
ユーザーのシステムで使用可能なビデオまたはオーディオ コンプレッサーを列挙するには、次の操作を行います。
- CoCreateInstance を呼び出して、CLSID_SystemDeviceEnumのクラス ID を持つシステム デバイス列挙子を作成します。
- フィルター カテゴリ GUID を使用して ICreateDevEnum::CreateClassEnumerator を呼び出します。 メソッドは IEnumMoniker インターフェイス ポインターを返します。
- デバイス モニカーを列挙するには、IEnumMoniker::Next メソッドを使用します。 このメソッドは、モニカーを表す IMoniker インターフェイスを返します。
モニカーからフレンドリ名を取得するには、次の操作を行います。
- IMoniker::BindToStorage メソッドを呼び出します。 このメソッドは 、IPropertyBag インターフェイス ポインターを返します。
- FriendlyName プロパティを読み取る場合は、IPropertyBag::Read メソッドを使用します。
通常、アプリケーションにはコンプレッサーの一覧が表示されるため、ユーザーは 1 つを選択できます。 たとえば、次のコードは、使用可能なビデオ コンプレッサーの名前をリスト ボックスに設定します。
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))
{
// Handle the error.
}
hr = pSysDevEnum->CreateClassEnumerator(
CLSID_VideoCompressorCategory, &pEnum, 0);
if (hr == S_OK) // S_FALSE means nothing in this category.
{
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))
{
// Use the filter.
// Remember to release the IBaseFilter interface.
}
VCM コーデックの場合、すべてのコーデックが同じ AVI 圧縮フィルターでラップされている場合でも、各モニカーは 1 つの特定のコーデックを表します。 BindToObject を呼び出すと、このフィルターのインスタンスが作成され、そのコーデック用に初期化されます。 このため、AVI 圧縮フィルターで CoCreateInstance を直接呼び出すことはできません。 システム デバイス列挙子を実行する必要があります。
関連トピック