Microsoft DirectX 9.0

Selecting a Capture Device

To select a capture device, use the System Device Enumerator, as described in the topic Using the System Device Enumerator. This helper object returns a collection of device monikers, selected by filter category. (A moniker is a COM object that contains information about another object, which enables the application to get information about the object without creating the object itself. Later, the application can use the moniker to create the object. For more information about monikers, see the documentation for IMoniker in the Platform SDK.)

For capture devices, the following categories are relevant.

Category GUID Description
CLSID_AudioInputDeviceCategory Audio capture devices
CLSID_VideoInputDeviceCategory Video capture devices

A device can appear in both categories. The following code creates an enumerator for video capture devices:

ICreateDevEnum *pDevEnum = NULL;
IEnumMoniker *pEnum = NULL;

// Create the System Device Enumerator.
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
    CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, 
    reinterpret_cast<void**>(&pDevEnum));
if (SUCCEEDED(hr))
{
    // Create an enumerator for the video capture category.
    hr = pDevEnum->CreateClassEnumerator(
        CLSID_VideoInputDeviceCategory,
        &pEnum, 0);
}

The IEnumMoniker interface returns a list of IMoniker interfaces, each of which represents a device moniker. Typically, you would display a list of devices and enable the user to select one. Call the IMoniker::BindToStorage method, which returns an IPropertyBag interface pointer, and then call IPropertyBag::Read to read properties from the moniker. Properties include the following.

Property Description
FriendlyName The name of the device.
Description A description of the device.
DevicePath A unique string.

The following code example shows how to populate a list box with the device names:

HWND hList; // Handle to the list box.
IMoniker *pMoniker = NULL;
while (pEnum->Next(1, &pMoniker, NULL) == S_OK)
{
    IPropertyBag *pPropBag;
    hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, 
        (void**)(&pPropBag));
    if (FAILED(hr))
    {
        pMoniker->Release();
        continue;  // Skip this one, maybe the next one will work.
    } 
    // Find the description or friendly name.
    VARIANT varName;
    VariantInit(&varName);
    hr = pPropBag->Read(L"Description", &varName, 0);
    if (FAILED(hr))
    {
        hr = pPropBag->Read(L"FriendlyName", &varName, 0);
    }
    if (SUCCEEDED(hr))
    {
        // Add it to the application's list box.
        USES_CONVERSION;
        (long)SendMessage(hList, LB_ADDSTRING, 0, 
            (LPARAM)OLE2T(varName.bstrVal));
        VariantClear(&varName); 
    }
    pPropBag->Release();
    pMoniker->Release();
}

When the user selects a device, create the capture filter for the device by calling IMoniker::BindToObject on the moniker. Then call AddFilter to add the filter to the filter graph:

IBaseFilter *pCap = NULL;
hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap);
if (SUCCEEDED(hr))
{
    hr = m_pGraph->AddFilter(pCap, L"Capture Filter");
}