Capture audio/vidéo en Media Foundation

Microsoft Media Foundation prend en charge la capture audio et vidéo. Les périphériques de capture vidéo sont pris en charge par le pilote de classe UVC et doivent être compatibles avec UVC 1,1. les périphériques de capture audio sont pris en charge via l’API de Session audio Windows (WASAPI).

Un périphérique de capture est représenté dans Media Foundation par un objet de source multimédia, qui expose l’interface IMFMediaSource . Dans la plupart des cas, l’application n’utilise pas directement cette interface, mais utilise une API de niveau supérieur, telle que le lecteur source , pour contrôler l’appareil de capture.

Énumérer les périphériques de capture

Pour énumérer les périphériques de capture sur le système, procédez comme suit :

  1. Appelez la fonction MFCreateAttributes pour créer un magasin d’attributs.

  2. Affectez l’une des valeurs suivantes à l’attribut de type de source de l' _ _ attribut _ _ DEVSOURCE MF :

    Valeur Description
    TYPE de source de l' _ attribut DEVSOURCE MF _ _ _ _ AUDCAP _ GUID Énumérer les périphériques de capture audio.
    TYPE de source de l' _ attribut DEVSOURCE MF _ _ _ _ VIDCAP _ GUID Énumérer les périphériques de capture vidéo.
  3. Appelez la fonction MFEnumDeviceSources . Cette fonction alloue un tableau de pointeurs IMFActivate . Chaque pointeur représente un objet d’activation pour un appareil sur le système.

  4. Appelez la méthode IMFActivate :: ActivateObject pour créer une instance de la source du média à partir de l’un des objets d’activation.

L’exemple suivant crée une source de média pour le premier appareil de capture vidéo dans la liste d’énumération :

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

Vous pouvez interroger les objets d’activation pour différents attributs, y compris les éléments suivants :

L’exemple suivant prend un tableau de pointeurs IMFActivate et imprime le nom complet de chaque appareil dans la fenêtre de débogage :

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

Si vous connaissez déjà le lien symbolique pour un périphérique vidéo, il existe une autre façon de créer la source du média pour l’appareil :

  1. Appelez MFCreateAttributes pour créer un magasin d’attributs.
  2. Définissez l’attribut de _ _ _ _ type de source de l’attribut MF DEVSOURCE sur le type de source d' _ attribut MF DEVSOURCE _ _ _ _ VIDCAP _ GUID.
  3. Définissez l’attribut de _ _ _ _ _ _ _ lien symbolique VIDCAP du type de source de l’attribut MF DEVSOURCE sur le lien symbolique.
  4. Appelez la fonction MFCreateDeviceSource ou MFCreateDeviceSourceActivate . La première retourne un pointeur IMFMediaSource . Ce dernier retourne un pointeur IMFActivate vers un objet d’activation. Vous pouvez utiliser l’objet d’activation pour créer la source. (Un objet d’activation peut être marshalé vers un autre processus, c’est pourquoi il est utile si vous souhaitez créer la source dans un autre processus. Pour plus d’informations, consultez objets d’activation.)

L’exemple suivant prend le lien symbolique d’un périphérique vidéo et crée une source de média.

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

Il existe une méthode équivalente pour créer un périphérique audio à partir de l’ID de point de terminaison audio :

  1. Appelez MFCreateAttributes pour créer un magasin d’attributs.
  2. Définissez l’attribut de _ _ _ _ type de source de l’attribut MF DEVSOURCE sur le type de source d' _ attribut MF DEVSOURCE _ _ _ _ AUDCAP _ GUID.
  3. Définissez l’attribut de l’ID de point de terminaison de l’attribut DEVSOURCE de l' _ attribut MF _ _ _ _ AUDCAP _ _ sur l’ID du point de terminaison.
  4. Appelez la fonction MFCreateDeviceSource ou MFCreateDeviceSourceActivate .

L’exemple suivant prend un ID de point de terminaison audio et crée une source de média.

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

Utiliser un appareil de capture

Une fois que vous avez créé la source du média pour un appareil de capture, utilisez le lecteur source pour obtenir les données de l’appareil. Le lecteur source fournit des exemples de supports qui contiennent les données audio de capture ou les trames vidéo. L’étape suivante dépend de votre scénario d’application :

  • Aperçu vidéo : utilisez Microsoft Direct3D ou Direct2D pour afficher la vidéo.
  • Capture de fichiers : utilisez le writer du récepteur pour encoder le fichier.
  • Aperçu audio : utilisez WASAPI.

Si vous souhaitez combiner la capture audio avec la capture vidéo, utilisez la source du média d’agrégation. La source du média d’agrégation contient une collection de sources de média et combine tous leurs flux dans un objet source de média unique. Pour créer une instance de la source du média d’agrégation, appelez la fonction MFCreateAggregateSource .

Arrêter l’appareil de capture

Lorsque l’appareil de capture n’est plus nécessaire, vous devez arrêter l’appareil en appelant Shutdown sur l’objet IMFMediaSource que vous avez obtenu en appelant MFCreateDeviceSource ou IMFActivate :: ActivateObject. L’échec de l’appel de Shutdown peut entraîner des liaisons de mémoire, car le système peut conserver une référence aux ressources IMFMediaSource jusqu’à l’appel de Shutdown .

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

Si vous avez alloué une chaîne contenant le lien symbolique vers un appareil de capture, vous devez également libérer cet objet.

    CoTaskMemFree(g_pwszSymbolicLink);
    g_pwszSymbolicLink = NULL;

    g_cchSymbolicLink = 0;

Capture audio/vidéo