選取擷取裝置
[與此頁面 相關的功能 DirectShow是舊版功能。 它已被 MediaPlayer、 IMFMediaEngine和 Media Foundation 中的音訊/視訊擷取取代。 這些功能已針對Windows 10和Windows 11進行優化。 Microsoft 強烈建議新程式碼盡可能使用 MediaPlayer、 IMFMediaEngine 和 音訊/視訊擷取 ,而不是 DirectShow。 Microsoft 建議盡可能重寫使用舊版 API 的現有程式碼,以使用新的 API。]
若要選取音訊或視訊擷取裝置,請使用 系統裝置列舉值,如 使用系統裝置列舉值主題中所述。 系統裝置列舉值會傳回依裝置類別選取的裝置 Moniker 集合。 Moniker是 COM 物件,其中包含另一個物件的相關資訊。 Monikers 可讓應用程式取得物件的相關資訊,而不需要實際建立物件。 稍後,應用程式可以使用 Moniker 來建立物件。 如需 Moniker 的詳細資訊,請參閱 IMoniker的檔。
若要使用系統裝置列舉值,請執行下列步驟。
呼叫 CoCreateInstance 以建立系統裝置列舉值的實例。
呼叫 ICreateDevEnum::CreateClassEnumerator ,並將裝置類別指定為 GUID。 針對擷取裝置,下列類別相關。
類別 GUID Description CLSID_AudioInputDeviceCategory 音訊擷取裝置 CLSID_VideoInputDeviceCategory 視訊擷取裝置 如果視訊相機具有整合式麥克風,則會出現在這兩個類別中。 不過,相機和麥克風會視為系統個別的裝置,以供列舉、裝置建立和資料串流之用。
CreateClassEnumerator方法會傳回IEnumMoniker介面的指標。 若要列舉 Monikers,請呼叫 IEnumMoniker::Next。
下列程式碼會為指定的裝置類別建立列舉值。
#include <windows.h>
#include <dshow.h>
#pragma comment(lib, "strmiids")
HRESULT EnumerateDevices(REFGUID category, IEnumMoniker **ppEnum)
{
// Create the System Device Enumerator.
ICreateDevEnum *pDevEnum;
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum));
if (SUCCEEDED(hr))
{
// Create an enumerator for the category.
hr = pDevEnum->CreateClassEnumerator(category, ppEnum, 0);
if (hr == S_FALSE)
{
hr = VFW_E_NOT_FOUND; // The category is empty. Treat as an error.
}
pDevEnum->Release();
}
return hr;
}
IEnumMoniker介面會列舉IMoniker介面的清單,每個介面都代表裝置 Moniker。 應用程式可以從 Moniker 讀取屬性,或使用 Moniker 建立裝置的 DirectShow 擷取篩選器。 Moniker 屬性會以 VARIANT 值傳回。 裝置 Moniker 支援下列屬性。
屬性 | Description | VARIANT 型別 |
---|---|---|
「FriendlyName」 | 裝置的名稱。 | VT_BSTR |
「Description」 | 裝置的描述。 | VT_BSTR |
「DevicePath」 | 識別裝置的唯一字串。 僅限 (視訊擷取裝置。) | VT_BSTR |
「WaveInID」 | 音訊擷取裝置的識別碼。 僅 (音訊擷取裝置。) | VT_I4 |
「FriendlyName」 和 「Description」 屬性適用于在 UI 中顯示。
- 「FriendlyName」 屬性適用于每個裝置。 它包含裝置的人類可讀取名稱。
- 「Description」 屬性僅適用于 DV 和 D-VHS/MPEG 攝影機裝置。 如需詳細資訊,請參閱 MSDV 驅動程式 和 MSTape 驅動程式。 如果有的話,它會包含比 「FriendlyName」 屬性更具體之裝置的描述。 通常它包含廠商名稱。
- 「DevicePath」 屬性不是人類可讀取的字串,但保證系統上每個視訊擷取裝置都是唯一的。 您可以使用這個屬性來區分相同裝置型號的兩個或多個實例。
- 如果存在 「WaveInID」 屬性,表示 DirectShow 擷取篩選器會在內部使用 波氏音訊 API 來與裝置通訊。 「WaveInID」 屬性的值會對應至 waveIn* 函式所使用的識別碼,例如 waveInOpen。
若要從 Moniker 讀取屬性,請執行下列步驟。
- 呼叫 IMoniker::BindToStorage 以取得 IPropertyBag 介面的指標。
- 呼叫 IPropertyBag::Read 以讀取屬性。
下列程式碼範例示範如何列舉裝置 Moniker 清單並取得屬性。
void DisplayDeviceInformation(IEnumMoniker *pEnum)
{
IMoniker *pMoniker = NULL;
while (pEnum->Next(1, &pMoniker, NULL) == S_OK)
{
IPropertyBag *pPropBag;
HRESULT hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
if (FAILED(hr))
{
pMoniker->Release();
continue;
}
VARIANT var;
VariantInit(&var);
// Get description or friendly name.
hr = pPropBag->Read(L"Description", &var, 0);
if (FAILED(hr))
{
hr = pPropBag->Read(L"FriendlyName", &var, 0);
}
if (SUCCEEDED(hr))
{
printf("%S\n", var.bstrVal);
VariantClear(&var);
}
hr = pPropBag->Write(L"FriendlyName", &var);
// WaveInID applies only to audio capture devices.
hr = pPropBag->Read(L"WaveInID", &var, 0);
if (SUCCEEDED(hr))
{
printf("WaveIn ID: %d\n", var.lVal);
VariantClear(&var);
}
hr = pPropBag->Read(L"DevicePath", &var, 0);
if (SUCCEEDED(hr))
{
// The device path is not intended for display.
printf("Device path: %S\n", var.bstrVal);
VariantClear(&var);
}
pPropBag->Release();
pMoniker->Release();
}
}
void main()
{
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (SUCCEEDED(hr))
{
IEnumMoniker *pEnum;
hr = EnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnum);
if (SUCCEEDED(hr))
{
DisplayDeviceInformation(pEnum);
pEnum->Release();
}
hr = EnumerateDevices(CLSID_AudioInputDeviceCategory, &pEnum);
if (SUCCEEDED(hr))
{
DisplayDeviceInformation(pEnum);
pEnum->Release();
}
CoUninitialize();
}
}
若要建立裝置的 DirectShow 擷取篩選器,請呼叫 IMoniker::BindToObject 方法來取得 IBaseFilter 指標。 然後呼叫 IFilterGraph::AddFilter 將篩選新增至篩選圖形:
IBaseFilter *pCap = NULL;
hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap);
if (SUCCEEDED(hr))
{
hr = m_pGraph->AddFilter(pCap, L"Capture Filter");
}
相關主題