Share via


비디오 디바이스 손실 처리

이 항목에서는 비디오 캡처 디바이스를 사용할 때 디바이스 손실을 감지하는 방법을 설명합니다. 여기에는 다음 단원이 포함되어 있습니다.

디바이스 알림 등록

디바이스에서 캡처를 시작하기 전에 RegisterDeviceNotification 함수를 호출하여 디바이스 알림에 등록합니다. 다음 코드와 같이 KSCATEGORY_CAPTURE 디바이스 클래스에 등록합니다.

#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;
}

비디오 캡처 디바이스 열거에 설명된 대로 시스템의 비디오 디바이스를 열거합니다. 목록에서 디바이스를 선택한 다음, 다음 코드와 같이 MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK 특성에 대한 활성화 개체를 쿼리합니다.

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
        );
}

WM_DEVICECHANGE 처리

메시지 루프에서 WM_DEVICECHANGE 메시지를 수신 대기합니다. lParam 메시지 매개 변수는 DEV_BROADCAST_HDR 구조체에 대한 포인터입니다.

    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;

다음으로, 다음과 같이 디바이스 알림 메시지를 디바이스의 기호 링크와 비교합니다.

  1. DEV_BROADCAST_HDR 구조체의 dbch_devicetype 멤버를 확인합니다. 값이 DBT_DEVTYP_DEVICEINTERFACE 경우 구조체 포인터를 DEV_BROADCAST_DEVICEINTERFACE 구조체로 캐스팅합니다.
  2. 이 구조체의 dbcc_name 멤버를 디바이스의 기호 링크와 비교합니다.
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;
}

알림 등록 취소

애플리케이션이 종료되기 전에 UnregisterDeviceNotification을 호출하여 디바이스 알림 등록을 취소합니다.

void OnClose(HWND /*hwnd*/)
{
    if (g_hdevnotify)
    {
        UnregisterDeviceNotification(g_hdevnotify);
    }

    PostQuitMessage(0);
}

비디오 캡처 디바이스 열거

비디오 캡처