Media Foundation でのオーディオ/ビデオ キャプチャ

Microsoft Media Foundation では、オーディオとビデオのキャプチャがサポートされています。 ビデオ キャプチャ デバイスは、UVC クラス ドライバーを介してサポートされており、UVC 1.1 と互換性がある必要があります。 オーディオ キャプチャ デバイスは、Windows Audio Session API (WASAPI) を介してサポートされています。

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

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

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

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

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

    説明
    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 関数を呼び出します。 前者は IMFMediaSource ポインターを返します。 後者は、アクティブ化オブジェクトへの 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;

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