Captura de áudio/vídeo no Media Foundation
O Microsoft Media Foundation oferece suporte à captura de áudio e vídeo. Os dispositivos de captura de vídeo são suportados através do driver da classe UVC e devem ser compatíveis com o UVC 1.1. Os dispositivos de captura de áudio são suportados através da API de Sessão de Áudio do Windows (WASAPI).
Um dispositivo de captura é representado no Media Foundation por um objeto de origem de mídia, que expõe a interface IMFMediaSource. Na maioria dos casos, o aplicativo não usará essa interface diretamente, mas usará uma API de nível superior, como o Leitor de código-fonte , para controlar o dispositivo de captura.
Enumerar dispositivos de captura
Para enumerar os dispositivos de captura no sistema, execute as seguintes etapas:
Chame a função MFCreateAttributes para criar um repositório de atributos.
Defina o atributo MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE para um dos seguintes valores:
Valor Descrição MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID Enumerar dispositivos de captura de áudio. MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID Enumerar dispositivos de captura de vídeo. Chame a função MFEnumDeviceSources. Essa função aloca uma matriz de ponteiros IMFActivate. Cada ponteiro representa um objeto de ativação para um dispositivo no sistema.
Chame o método IMFActivate::ActivateObject para criar uma instância da fonte de mídia de um dos objetos de ativação.
O exemplo a seguir cria uma fonte de mídia para o primeiro dispositivo de captura de vídeo na lista de enumeração:
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;
}
Você pode consultar os objetos de ativação para vários atributos, incluindo o seguinte:
- O atributo MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME contém o nome de exibição do dispositivo. O nome de exibição é adequado para exibição ao usuário, mas pode não ser exclusivo.
- Para dispositivos de vídeo, o atributo MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK contém o link simbólico para o dispositivo. O link simbólico identifica exclusivamente o dispositivo no sistema, mas não é uma cadeia de caracteres legível.
- Para dispositivos de áudio, o atributo MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID contém o ID do ponto de extremidade de áudio do dispositivo. O ID do ponto de extremidade de áudio é semelhante a um link simbólico. Ele identifica exclusivamente o dispositivo no sistema, mas não é uma cadeia de caracteres legível.
O exemplo a seguir usa uma matriz de ponteiros IMFActivate e imprime o nome de exibição de cada dispositivo na janela de depuração:
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);
}
}
Se você já conhece o link simbólico para um dispositivo de vídeo, há outra maneira de criar a fonte de mídia para o dispositivo:
- Chame MFCreateAttributes para criar um repositório de atributos.
- Defina o atributo MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE como MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID.
- Defina o atributo MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK para o link simbólico.
- Chame a função MFCreateDeviceSource ou MFCreateDeviceSourceActivate. O primeiro retorna um ponteiro IMFMediaSource. Este último retorna um ponteiro IMFActivate para um objeto de ativação. Você pode usar o objeto de ativação para criar a origem. (Um objeto de ativação pode ser empacotado para outro processo, portanto, é útil se você quiser criar a origem em outro processo. Para obter mais informações, consulte Objetos de ativação.)
O exemplo a seguir usa o link simbólico de um dispositivo de vídeo e cria uma fonte 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;
}
Há uma maneira equivalente de criar um dispositivo de áudio a partir do ID do ponto de extremidade de áudio:
- Chame MFCreateAttributes para criar um repositório de atributos.
- Defina o atributo MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE como MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID.
- Defina o atributo MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID para o ID do ponto de extremidade.
- Chame a função MFCreateDeviceSource ou MFCreateDeviceSourceActivate.
O exemplo a seguir usa uma ID de ponto de extremidade de áudio e cria uma fonte 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;
}
Usar um dispositivo de captura
Depois de criar a fonte de mídia para um dispositivo de captura, use o Leitor de código-fonte para obter dados do dispositivo. O Leitor de Origem fornece amostras de mídia que contêm os dados de áudio de captura ou quadros de vídeo. A próxima etapa depende do cenário do aplicativo:
- Visualização de vídeo: use o Microsoft Direct3D ou Direct2D para exibir o vídeo.
- Captura de arquivo: use o Sink Writer para codificar o arquivo.
- Pré-visualização de áudio: Use WASAPI.
Se você quiser combinar a captura de áudio com a captura de vídeo, use a fonte de mídia agregada. A fonte de mídia agregada contém uma coleção de fontes de mídia e combina todos os seus fluxos em um único objeto de fonte de mídia. Para criar uma instância da fonte de mídia agregada, chame a função MFCreateAggregateSource.
Desligue o dispositivo de captura
Quando o dispositivo de captura não for mais necessário, você deverá desligá-lo chamando Shutdown no objeto IMFMediaSource obtido chamando MFCreateDeviceSource ou IMFActivate::ActivateObject. A falha ao chamar o desligamento pode resultar em vazamentos de memória porque o sistema pode manter uma referência aos recursos do IMFMediaSource até que o desligamento seja chamado.
if (g_pSource)
{
g_pSource->Shutdown();
g_pSource->Release();
g_pSource = NULL;
}
Se você alocou uma cadeia de caracteres contendo o link simbólico para um dispositivo de captura, você deve liberar esse objeto também.
CoTaskMemFree(g_pwszSymbolicLink);
g_pwszSymbolicLink = NULL;
g_cchSymbolicLink = 0;
Tópicos relacionados