ビデオ デバイスの損失の処理

このトピックでは、ビデオ キャプチャ デバイスを使用するときにデバイスの損失を検出する方法について説明します。 次のセクションが含まれます。

デバイス通知に登録する

デバイスからのキャプチャを開始する前に、 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);
}

ビデオ キャプチャ デバイスの列挙

ビデオ キャプチャ