次の方法で共有


圧縮フィルターの選択

[このページに関連付けられている機能 DirectShow は、従来の機能です。 MediaPlayer、IMFMediaEngine、Media Foundation のオーディオ/ビデオ キャプチャに置き換わりました。 これらの機能は、Windows 10とWindows 11用に最適化されています。 新しいコードでは、可能であれば、DirectShow ではなく Media Foundation で MediaPlayerIMFMediaEngineAudio/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 フィルターのインスタンスを表します。 モニカーを使用してフィルターを作成したり、フィルターを作成せずにデバイスのフレンドリ名を取得したりできます。

ユーザーのシステムで使用可能なビデオまたはオーディオ コンプレッサーを列挙するには、次の操作を行います。

  1. CoCreateInstance を呼び出して、CLSID_SystemDeviceEnumのクラス ID を持つシステム デバイス列挙子を作成します。
  2. フィルター カテゴリ GUID を使用して ICreateDevEnum::CreateClassEnumerator を呼び出します。 メソッドは IEnumMoniker インターフェイス ポインターを返します。
  3. デバイス モニカーを列挙するには、IEnumMoniker::Next メソッドを使用します。 このメソッドは、モニカーを表す IMoniker インターフェイスを返します。

モニカーからフレンドリ名を取得するには、次の操作を行います。

  1. IMoniker::BindToStorage メソッドを呼び出します。 このメソッドは 、IPropertyBag インターフェイス ポインターを返します。
  2. 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 を直接呼び出すことはできません。 システム デバイス列挙子を実行する必要があります。

AVI ファイルの再圧縮