Audio-/Videoaufnahme in Media Foundation

Microsoft Media Foundation unterstützt Audio- und Videoaufnahmen. Videoaufnahmegeräte werden über den UVC-Klassentreiber unterstützt und müssen mit UVC 1.1 kompatibel sein. Audioaufnahmegeräte werden über die Windows Audio Session API (WASAPI) unterstützt.

Ein Aufnahmegerät wird in Media Foundation durch ein Medienquellobjekt dargestellt, das die IMFMediaSource-Schnittstelle verfügbar macht. In den meisten Fällen verwendet die Anwendung diese Schnittstelle nicht direkt. Stattdessen steuert sie das Aufnahmegerät mit einer API auf höherer Ebene, z. B. mit dem Quellleser.

Aufzählen von Aufnahmegeräten

Führen Sie zum Aufzählen der Aufnahmegeräte im System die folgenden Schritte aus:

  1. Rufen Sie die MFCreateAttributes-Funktion auf, um einen Attributspeicher zu erstellen.

  2. Legen Sie das MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE-Attribut auf einen der folgenden Werte fest:

    Wert Beschreibung
    MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID Aufzählen von Audioaufnahmegeräten.
    MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID Aufzählen von Videoaufnahmegeräten.

     

  3. Rufen Sie die MFEnumDeviceSources-Funktion auf. Diese Funktion weist ein Array von IMFActivate-Zeigern zu. Jeder Zeiger stellt ein Aktivierungsobjekt für ein Gerät im System dar.

  4. Rufen Sie die IMFActivate::ActivateObject-Methode auf, um eine Instanz der Medienquelle aus einem der Aktivierungsobjekte zu erstellen.

Im folgenden Beispiel wird eine Medienquelle für das erste Videoaufnahmegerät in der Enumerationsliste erstellt:

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;
}

Sie können die Aktivierungsobjekte nach verschiedenen Attributen abfragen, einschließlich der folgenden:

  • Das MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME-Attribut enthält den Anzeigenamen des Geräts. Der Anzeigename eignet sich zur Veranschaulichung für Benutzer*innen, ist jedoch möglicherweise nicht eindeutig.
  • Für Videogeräte enthält das MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK-Attribut die symbolische Verknüpfung mit dem Gerät. Die symbolische Verknüpfung identifiziert das Gerät auf dem System eindeutig, ist jedoch keine lesbare Zeichenfolge.
  • Für Audiogeräte enthält das MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID-Attribut die Audioendpunkt-ID des Geräts. Die Audioendpunkt-ID ähnelt einer symbolischen Verknüpfung. Sie identifiziert das Gerät auf dem System eindeutig, ist aber keine lesbare Zeichenfolge.

Im folgenden Beispiel wird ein Array von IMFActivate-Zeigern verwendet und der Anzeigename jedes Geräts im Debugfenster ausgegeben:

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);
    }
}

Wenn Sie die symbolische Verknüpfung für ein Videogerät bereits kennen, gibt es eine weitere Möglichkeit, die Medienquelle für das Gerät zu erstellen:

  1. Rufen Sie MFCreateAttributes auf, um einen Attributspeicher zu erstellen.
  2. Legen Sie das MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE-Attribut auf MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID fest.
  3. Legen Sie das MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK-Attribut auf die symbolische Verknüpfung fest.
  4. Rufen Sie entweder die MFCreateDeviceSource- oder die MFCreateDeviceSourceActivate-Funktion auf. Die Erstere gibt einen IMFMediaSource-Zeiger zurück. Die Letztere gibt einen IMFActivate-Zeiger auf ein Aktivierungsobjekt zurück. Sie können mit dem Aktivierungsobjekt die Quelle erstellen. (Ein Aktivierungsobjekt kann auf einen anderen Prozess gemarshallt werden. Es ist daher nützlich, wenn Sie die Quelle in einem anderen Prozess erstellen möchten. Weitere Informationen finden Sie unter Aktivierungsobjekte.)

Im folgenden Beispiel wird die symbolische Verknüpfung eines Videogeräts verwendet und eine Medienquelle erstellt.

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;    
}

Auf die gleiche Weise kann ein Audiogerät aus der Audioendpunkt-ID erstellt werden:

  1. Rufen Sie MFCreateAttributes auf, um einen Attributspeicher zu erstellen.
  2. Legen Sie das MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE-Attribut auf MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID fest.
  3. Legen Sie das MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID-Attribut auf die Endpunkt-ID fest.
  4. Rufen Sie entweder die MFCreateDeviceSource- oder die MFCreateDeviceSourceActivate-Funktion auf.

Im folgenden Beispiel wird anhand einer Audioendpunkt-ID eine Medienquelle erstellt.

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;    
}

Verwenden eines Aufnahmegeräts

Nachdem Sie die Medienquelle für ein Aufnahmegerät erstellt haben, rufen Sie mit dem Quellleser Daten vom Gerät ab. Der Quellleser liefert Medienbeispiele, die die aufgenommenen Audiodaten oder Videoframes enthalten. Der nächste Schritt hängt von Ihrem Anwendungsszenario ab:

  • Videovorschau: Zeigen Sie das Video mit Microsoft Direct3D oder Direct2D an.
  • Dateierfassung: Codieren Sie die Datei mit dem Senkenschreiber.
  • Audiovorschau: Verwenden Sie WASAPI.

Wenn Sie die Audioaufnahme mit der Videoaufnahme kombinieren möchten, verwenden Sie die aggregierte Medienquelle. Die aggregierte Medienquelle enthält eine Sammlung von Medienquellen und kombiniert deren Datenströme in einem einzelnen Medienquellobjekt. Rufen Sie zum Erstellen einer Instanz der Aggregatmedienquelle die MFCreateAggregateSource-Funktion auf.

Fahren Sie das Aufnahmegerät herunter.

Wenn das Aufnahmegerät nicht mehr benötigt wird, müssen Sie das Gerät herunterfahren. Rufen Sie dazu Shutdown für das IMFMediaSource-Objekt auf, das Sie mit dem Aufrufen von MFCreateDeviceSource oder IMFActivate::ActivateObject erhalten haben. Fehler beim Aufrufen von Shutdown können zu Speicherverlusten führen, da das System möglicherweise einen Verweis auf IMFMediaSource-Ressourcen bis zum Aufruf von Shutdown beibehält.

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

Wenn Sie eine Zeichenfolge zugewiesen haben, die die symbolische Verknüpfung zu einem Aufnahmegerät enthält, sollten Sie dieses Objekt ebenfalls freigeben.

    CoTaskMemFree(g_pwszSymbolicLink);
    g_pwszSymbolicLink = NULL;

    g_cchSymbolicLink = 0;

Audio-/Videoaufnahme