Captura de audio y vídeo en Media Foundation

Microsoft Media Foundation admite la captura de audio y vídeo. Los dispositivos de captura de vídeo se admiten a través del controlador de clase UVC y deben ser compatibles con UVC 1.1. Los dispositivos de captura de audio se admiten a través de la API de sesión de audio de Windows (WASAPI).

Un dispositivo de captura se representa en Media Foundation mediante un objeto de origen multimedia, que expone la interfaz IMFMediaSource. En la mayoría de los casos, la aplicación no usará esta interfaz directamente, sino que usará una API de nivel superior, como el Lector de origen para controlar el dispositivo de captura.

Enumerar dispositivos de captura

Para enumerar los dispositivos de captura en el sistema, realice los pasos siguientes:

  1. Llame a la función MFCreateAttributes para crear un almacén de atributos.

  2. Establezca el atributo MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE en uno de los siguientes valores:

    Valor Descripción
    MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID Enumerar dispositivos de captura de audio.
    MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID Enumerar dispositivos de captura de vídeo.

     

  3. Llame a la función MFEnumDeviceSources. Esta función asigna una matriz de punteros IMFActivate. Cada puntero representa un objeto de activación para un dispositivo del sistema.

  4. Llame al método IMFActivate::ActivateObject para crear una instancia del origen multimedia a partir de uno de los objetos de activación.

En el ejemplo siguiente se crea un origen multimedia para el primer dispositivo de captura de vídeo de la lista de enumeraciones:

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

Puede consultar los objetos de activación para varios atributos, incluidos los siguientes:

  • El atributo MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME contiene el nombre de visualización del dispositivo. El nombre de visualización es adecuado para mostrar al usuario, pero es posible que no sea único.
  • En el caso de los dispositivos de vídeo, el atributo MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK contiene el vínculo simbólico al dispositivo. El vínculo simbólico identifica de forma única el dispositivo en el sistema, pero no es una cadena legible.
  • En el caso de los dispositivos de audio, el atributo MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID contiene el identificador de punto de conexión de audio del dispositivo. El identificador del punto de conexión de audio es similar a un vínculo simbólico. Identifica de forma única el dispositivo en el sistema, pero no es una cadena legible.

En el ejemplo siguiente se toma una matriz de punteros IMFActivate y se imprime el nombre de visualización de cada dispositivo en la ventana de depuración:

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 ya conoce el vínculo simbólico de un dispositivo de vídeo, hay otra manera de crear el origen multimedia para el dispositivo:

  1. Llame a MFCreateAttributes para crear un almacén de atributos.
  2. Establezca el atributo MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE en MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID.
  3. Establezca el atributo MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK en el vínculo simbólico.
  4. Llame a la función MFCreateDeviceSource o MFCreateDeviceSourceActivate. El primero devuelve un puntero IMFMediaSource. El último devuelve un puntero IMFActivate a un objeto de activación. Puede usar el objeto de activación para crear el origen. (Un objeto de activación se puede serializar en otro proceso, por lo que resulta útil si desea crear el origen en otro proceso. Para obtener más información, vea Objetos de activación).

En el ejemplo siguiente se toma el vínculo simbólico de un dispositivo de vídeo y se crea un origen multimedia.

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

Hay una manera equivalente de crear un dispositivo de audio a partir del identificador de punto de conexión de audio:

  1. Llame a MFCreateAttributes para crear un almacén de atributos.
  2. Establezca el atributo MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE en MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID.
  3. Establezca el atributo MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID en el identificador del punto de conexión.
  4. Llame a la función MFCreateDeviceSource o MFCreateDeviceSourceActivate.

En el ejemplo siguiente se toma un identificador de punto de conexión de audio y se crea un origen multimedia.

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

Usar un dispositivo de captura

Después de crear el origen multimedia para un dispositivo de captura, use el Lector de origen para obtener datos del dispositivo. El Lector de origen ofrece muestras multimedia que contienen los datos de audio de captura o fotogramas de vídeo. El siguiente paso depende del escenario de aplicación:

  • Vista previa del vídeo: use Microsoft Direct3D o Direct2D para mostrar el vídeo.
  • Captura de archivos: use el Escritor receptor para codificar el archivo.
  • Vista previa de audio: use WASAPI.

Si desea combinar la captura de audio con captura de vídeo, use el origen multimedia agregado. El origen multimedia agregado contiene una colección de orígenes multimedia y combina todas sus secuencias en un único objeto de origen multimedia. Para crear una instancia del origen multimedia agregado, llame a la función MFCreateAggregateSource.

Apagar el dispositivo de captura

Cuando el dispositivo de captura ya no sea necesario, debe apagar el dispositivo llamando a Shutdown en el objeto IMFMediaSource que obtuvo llamando a MFCreateDeviceSource o IMFActivate::ActivateObject. Si no se llama a Shutdown, se pueden producir pérdidas de memoria porque el sistema puede mantener una referencia a los recursos IMFMediaSource hasta que se llame a Shutdown.

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

Si ha asignado una cadena que contiene el vínculo simbólico a un dispositivo de captura, también debe liberar este objeto.

    CoTaskMemFree(g_pwszSymbolicLink);
    g_pwszSymbolicLink = NULL;

    g_cchSymbolicLink = 0;

Captura de audio y vídeo