媒體基礎中的音訊/視訊擷取
Microsoft Media Foundation 支援音訊和視訊擷取。 視訊擷取裝置可透過UVC類別驅動程式支援,且必須與UVC 1.1相容。 音訊擷取裝置可透過 Windows 音訊工作階段 API (WASAPI) 支援。
擷取裝置是由媒體來源對象在媒體基礎中表示,該物件會 公開IMFMediaSource 介面。 在大部分情況下,應用程式不會直接使用此介面,但會使用較高層級的 API,例如 來源讀取器 來控制擷取裝置。
列舉擷取裝置
若要列舉系統上的擷取裝置,請執行下列步驟:
呼叫 MFCreateAttributes 函式來建立屬性存放區。
將 MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE 屬性設定為下列其中一個值:
值 Description MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID 列舉音訊擷取裝置。 MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID 列舉影片擷取裝置。 呼叫 MFEnumDeviceSources 函式。 此函式會配置IMFActivate指標的陣列。 每個指標都代表系統上一部裝置的啟用物件。
呼叫 IMFActivate::ActivateObject 方法,從其中一個啟用物件建立媒體來源的實例。
下列範例會在列舉清單中建立第一個視訊擷取裝置的媒體來源:
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 屬性包含裝置的音訊端點標識符。 音訊端點標識碼類似於符號連結。 它會唯一識別系統上的裝置,但不是可讀取的字串。
下列範例會採用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);
}
}
如果您已經知道視訊裝置的符號連結,有另一種方式可建立裝置的媒體來源:
- 呼叫 MFCreateAttributes 以建立屬性存放區。
- 將 MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE 屬性設定為 MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID。
- 將 MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK 屬性設定為符號連結。
- 呼叫 MFCreateDeviceSource 或 MFCreateDeviceSourceActivate 函式。 前者會傳 回IMFMediaSource 指標。 後者會傳 回啟用物件的IMFActivate 指標。 您可以使用啟用物件來建立來源。 (啟用物件可以封送處理至另一個進程,因此如果您想要在另一個進程中建立來源,這會很有用。如需詳細資訊,請參閱 Activation Objects。)
下列範例會採用視訊裝置的符號連結,並建立媒體來源。
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;
}
從音訊端點標識元建立音訊裝置的方式相同:
- 呼叫 MFCreateAttributes 以建立屬性存放區。
- 將 MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE 屬性設定為 MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID。
- 將 MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID 屬性設定為端點標識碼。
- 呼叫 MFCreateDeviceSource 或 MFCreateDeviceSourceActivate 函式。
下列範例會採用音訊端點標識符,並建立媒體來源。
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;
}
使用擷取裝置
建立擷取裝置的媒體來源之後,請使用 來源讀取器 從裝置取得數據。 來源讀取器會提供包含擷取音訊數據或視訊畫面的媒體範例。 下一個步驟取決於您的應用程式案例:
如果您想要結合音訊擷取與視訊擷取,請使用 匯總媒體來源。 匯總媒體來源包含媒體來源的集合,並將其所有數據流合併成單一媒體來源物件。 若要建立匯總媒體來源的實例,請呼叫 MFCreateAggregateSource 函式。
關閉擷取裝置
當不再需要擷取裝置時,您必須在呼叫 MFCreateDeviceSource 或 IMFActivate::ActivateObject 取得的 IMFMediaSource 物件上呼叫 Shutdown 來關閉裝置。 呼叫 Shutdown 可能會導致記憶體流失,因為系統可能會保留 IMFMediaSource 資源的參考,直到呼叫 Shutdown 為止。
if (g_pSource)
{
g_pSource->Shutdown();
g_pSource->Release();
g_pSource = NULL;
}
如果您配置了包含擷取裝置符號連結的字串,則也應該釋放此物件。
CoTaskMemFree(g_pwszSymbolicLink);
g_pwszSymbolicLink = NULL;
g_cchSymbolicLink = 0;
相關主題