メディア ファンデーションのオーディオ/ビデオ キャプチャ

Microsoft Media Foundation では、オーディオとビデオを取り込むことができます。 ビデオ キャプチャはデバイスに UVC クラス ドライバーを使用することでサポートされるため、UVC 1.1 と互換性があることが必要です。 オーディオ キャプチャはデバイスに Windows Audio Session API (WASAPI) を使用することでサポートされます。

キャプチャ デバイスは、Media Foundation 内で IMFMediaSource インターフェイスを公開するメディア ソース オブジェクトによって表現されます。 ほとんどのアプリケーションで、このインターフェイスは直接には使用されませんが、ソース リーダーなどの上位レベルの API が、キャプチャ デバイスを制御するために使用されます。

キャプチャ デバイスを列挙する

システム上のキャプチャ デバイスを列挙するには、次の手順を実行します。

  1. MFCreateAttributes 関数を呼び出して属性ストアを作成します。

  2. MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE 属性を次のいずれかの値に設定します。

    Value 説明
    MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID オーディオ キャプチャ デバイスを列挙します。
    MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID ビデオ キャプチャ デバイスを列挙します。

     

  3. MFEnumDeviceSources 関数を呼び出します。 この関数によって、IMFActivate ポインターの配列が割り当てられます。 各ポインターは、システム上の 1 つのデバイスをアクティブ化するオブジェクトを表します。

  4. IMFActivate::ActivateObject メソッドを呼び出して、1 つのアクティブ化オブジェクトからメディア ソースのインスタンスを作成します。

次の例では、列挙リストの最初のビデオ キャプチャ デバイスにメディア ソースが作成されます。

HRESULT CreateVideoCaptureDevice(IMFMediaSource **ppSource)
{
    *ppSource = NULL;

    UINT32 count = 0;

    IMFAttributes *pConfig = NULL;
    IMFActivate **ppDevices = NULL;

    // Create an attribute store to hold the search criteria.
    HRESULT hr = MFCreateAttributes(&pConfig, 1);

    // Request video capture devices.
    if (SUCCEEDED(hr))
    {
        hr = pConfig->SetGUID(
            MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, 
            MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
            );
    }

    // Enumerate the devices,
    if (SUCCEEDED(hr))
    {
        hr = MFEnumDeviceSources(pConfig, &ppDevices, &count);
    }

    // Create a media source for the first device in the list.
    if (SUCCEEDED(hr))
    {
        if (count > 0)
        {
            hr = ppDevices[0]->ActivateObject(IID_PPV_ARGS(ppSource));
        }
        else
        {
            hr = MF_E_NOT_FOUND;
        }
    }

    for (DWORD i = 0; i < count; i++)
    {
        ppDevices[i]->Release();
    }
    CoTaskMemFree(ppDevices);
    return hr;
}

次のようなさまざまな属性を持つアクティブ化オブジェクトに対してクエリを実行できます。

  • MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME 属性には、デバイスの表示名を定義します。 表示名はユーザーにわかりやすい名前が使用されますが、一意ではない可能性があります。
  • ビデオ デバイスの場合、MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK 属性にはデバイスへのシンボリック リンクが定義されます。 シンボリック リンクではシステム上のデバイスを一意に識別できますが、読み取り可能な文字列ではありません。
  • オーディオ デバイスの場合、 MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID 属性にはデバイスのオーディオ エンドポイント ID が定義されます。 オーディオ エンドポイント ID はシンボリック リンクと同様に、 システム上のデバイスを一意に識別しますが、読み取り可能な文字列ではありません。

次の例は、IMFActivate ポインターの配列を受け取り、各デバイスの表示名をデバッグ ウィンドウに出力します。

void DebugShowDeviceNames(IMFActivate **ppDevices, UINT count)
{
    for (DWORD i = 0; i < count; i++)
    {
        HRESULT hr = S_OK;
        WCHAR *szFriendlyName = NULL;
    
        // Try to get the display name.
        UINT32 cchName;
        hr = ppDevices[i]->GetAllocatedString(
            MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME,
            &szFriendlyName, &cchName);

        if (SUCCEEDED(hr))
        {
            OutputDebugString(szFriendlyName);
            OutputDebugString(L"\n");
        }
        CoTaskMemFree(szFriendlyName);
    }
}

ビデオ デバイスのシンボリック リンクについて理解していれば、デバイスのメディア ソースを別の方法で作成することもできます。

  1. MFCreateAttributes を呼び出して、属性ストアを作成します。
  2. MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE 属性を MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID に設定します。
  3. MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK 属性をシンボリック リンクに設定します。
  4. MFCreateDeviceSource 関数または MFCreateDeviceSourceActivate 関数を呼び出します。 MFCreateDeviceSource を呼び出すと、IMFMediaSource ポインターが返されます。 MFCreateDeviceSourceActivate を呼び出すと、IMFActivate ポインターがアクティブ化オブジェクトに返されます。 アクティブ化オブジェクトを使用してソースを作成します。 (アクティブ化オブジェクトは別のプロセスにマーシャリングできるため、ソースを別のプロセスで作成する場合に便利です。詳細については、アクティブ化オブジェクトを参照してください。)

次の例は、ビデオ デバイスのシンボリック リンクを受け取り、メディア ソースを作成します。

HRESULT CreateVideoCaptureDevice(PCWSTR *pszSymbolicLink, IMFMediaSource **ppSource)
{
    *ppSource = NULL;
    
    IMFAttributes *pAttributes = NULL;
    IMFMediaSource *pSource = NULL;

    HRESULT hr = MFCreateAttributes(&pAttributes, 2);

    // Set the device type to video.
    if (SUCCEEDED(hr))
    {
        hr = pAttributes->SetGUID(
            MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
            MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
            );
    }


    // Set the symbolic link.
    if (SUCCEEDED(hr))
    {
        hr = pAttributes->SetString(
            MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK,
            (LPCWSTR)pszSymbolicLink
            );            
    }

    if (SUCCEEDED(hr))
    {
        hr = MFCreateDeviceSource(pAttributes, ppSource);
    }

    SafeRelease(&pAttributes);
    return hr;    
}

同じように、オーディオ デバイスもオーディオ エンドポイント ID から作成できます。

  1. MFCreateAttributes を呼び出して、属性ストアを作成します。
  2. MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE 属性を MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID に設定します。
  3. MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID 属性をエンドポイント ID に設定します。
  4. MFCreateDeviceSource 関数または MFCreateDeviceSourceActivate 関数を呼び出します。

次の例は、オーディオ エンドポイント ID を受け取り、メディア ソースを作成します。

HRESULT CreateAudioCaptureDevice(PCWSTR *pszEndPointID, IMFMediaSource **ppSource)
{
    *ppSource = NULL;
    
    IMFAttributes *pAttributes = NULL;
    IMFMediaSource *pSource = NULL;

    HRESULT hr = MFCreateAttributes(&pAttributes, 2);

    // Set the device type to audio.
    if (SUCCEEDED(hr))
    {
        hr = pAttributes->SetGUID(
            MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
            MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID
            );
    }

    // Set the endpoint ID.
    if (SUCCEEDED(hr))
    {
        hr = pAttributes->SetString(
            MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID,
            (LPCWSTR)pszEndPointID
            ); 
    }

    if (SUCCEEDED(hr))
    {
        hr = MFCreateDeviceSource(pAttributes, ppSource);
    }

    SafeRelease(&pAttributes);
    return hr;    
}

キャプチャ デバイスの使用

キャプチャ デバイスのメディア ソースを作成した後、ソース リーダーを使用してデバイスからデータを取得します。 ソース リーダーでは、キャプチャしたオーディオ データやビデオ フレームを含むメディア サンプルを取得できます。 その次の手順はアプリケーションの種類によって異なります。

  • ビデオ プレビュー: Microsoft Direct3D または Direct2D を使用してビデオを表示します。
  • ファイル キャプチャ: シンク ライターを使用してファイルをエンコードします。
  • オーディオ プレビュー: WASAPI を使用します。

オーディオ キャプチャをビデオ キャプチャと組み合わせる場合は、集約メディア ソースを使用します。 集約メディア ソースには、メディア ソースのコレクションが含まれており、1 つのメディア ソース オブジェクトにすべてのストリームが結合されます。 集約メディア ソースのインスタンスを作成するには、MFCreateAggregateSource 関数を呼び出します。

キャプチャ デバイスをシャット ダウンします。

キャプチャ デバイスが不要になった場合は、MFCreateDeviceSource または IMFActivate::ActivateObject を呼び出して取得した IMFMediaSource オブジェクトで Shutdown を呼び出してデバイスをシャットダウンする必要があります。 Shutdown の呼び出しが失敗しても、システムは Shutdown が呼び出されるまで IMFMediaSource の参照を続けるため、メモリ リークが発生する可能性があります。

if (g_pSource)
{
    g_pSource->Shutdown();
    g_pSource->Release();
    g_pSource = NULL;
}

キャプチャ デバイスへのシンボリック リンクを含む文字列を割り当てている場合は、このオブジェクトも解放してください。

    CoTaskMemFree(g_pwszSymbolicLink);
    g_pwszSymbolicLink = NULL;

    g_cchSymbolicLink = 0;

オーディオ/ビデオのキャプチャ