Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
This topic describes how to detect device loss when using a video capture device. It contains the following sections:
- Register For Device Notification
- Get the Symbolic Link of the Device
- Handle WM_DEVICECHANGE
- Unregister For Notification
- Related topics
Register For Device Notification
Before you start capturing from the device, call the RegisterDeviceNotification function to register for device notifications. Register for the KSCATEGORY_CAPTURE device class, as shown in the following code.
#include <Dbt.h>
#include <ks.h>
#include <ksmedia.h>
HDEVNOTIFY g_hdevnotify = NULL;
BOOL RegisterForDeviceNotification(HWND hwnd)
{
DEV_BROADCAST_DEVICEINTERFACE di = { 0 };
di.dbcc_size = sizeof(di);
di.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
di.dbcc_classguid = KSCATEGORY_CAPTURE;
g_hdevnotify = RegisterDeviceNotification(
hwnd,
&di,
DEVICE_NOTIFY_WINDOW_HANDLE
);
if (g_hdevnotify == NULL)
{
return FALSE;
}
return TRUE;
}
Get the Symbolic Link of the Device
Enumerate the video devices on the system, as described in Enumerating Video Capture Devices. Choose a device from the list, and then query the activation object for the MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK attribute, as shown in the following code.
WCHAR *g_pwszSymbolicLink = NULL;
UINT32 g_cchSymbolicLink = 0;
HRESULT GetSymbolicLink(IMFActivate *pActivate)
{
return pActivate->GetAllocatedString(
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK,
&g_pwszSymbolicLink,
&g_cchSymbolicLink
);
}
Handle WM_DEVICECHANGE
In your message loop, listen for WM_DEVICECHANGE messages. The lParam message parameter is a pointer to a DEV_BROADCAST_HDR structure.
case WM_DEVICECHANGE:
if (lParam != 0)
{
HRESULT hr = S_OK;
BOOL bDeviceLost = FALSE;
hr = CheckDeviceLost((PDEV_BROADCAST_HDR)lParam, &bDeviceLost);
if (FAILED(hr) || bDeviceLost)
{
CloseDevice();
MessageBox(hwnd, L"Lost the capture device.", NULL, MB_OK);
}
}
return TRUE;
Next, compare the device notification message against the symbolic link of your device, as follows:
- Check the dbch_devicetype member of the DEV_BROADCAST_HDR structure. If the value is DBT_DEVTYP_DEVICEINTERFACE, cast the structure pointer to a DEV_BROADCAST_DEVICEINTERFACE structure.
- Compare the dbcc_name member of this structure to the symbolic link of the device.
HRESULT CheckDeviceLost(DEV_BROADCAST_HDR *pHdr, BOOL *pbDeviceLost)
{
DEV_BROADCAST_DEVICEINTERFACE *pDi = NULL;
if (pbDeviceLost == NULL)
{
return E_POINTER;
}
*pbDeviceLost = FALSE;
if (g_pSource == NULL)
{
return S_OK;
}
if (pHdr == NULL)
{
return S_OK;
}
if (pHdr->dbch_devicetype != DBT_DEVTYP_DEVICEINTERFACE)
{
return S_OK;
}
// Compare the device name with the symbolic link.
pDi = (DEV_BROADCAST_DEVICEINTERFACE*)pHdr;
if (g_pwszSymbolicLink)
{
if (_wcsicmp(g_pwszSymbolicLink, pDi->dbcc_name) == 0)
{
*pbDeviceLost = TRUE;
}
}
return S_OK;
}
Unregister For Notification
Before the application exits, call UnregisterDeviceNotification to unregister for device notifications/
void OnClose(HWND /*hwnd*/)
{
if (g_hdevnotify)
{
UnregisterDeviceNotification(g_hdevnotify);
}
PostQuitMessage(0);
}
Related topics