使用 IMFSourceReaderCallback 检测 USB 相机断开连接

Detect USB camera disconnection using IMFSourceReaderCallback

我正在使用 IMFSourceReaderCallback 异步 C++ 实现来读取和处理 USB 摄像头视频流

它工作正常,除了如果相机被拔掉(这经常发生,因为我们使用了很多 USB 中继器),我没有收到通知。这是代码的摘录:

HRESULT CMFSourceReaderCallback::OnEvent(DWORD dwStreamIndex, IMFMediaEvent *pEvent)
{
    // I was hoping to get an Event here if I lost the camera, but no...
    // The break point nether hits, and from EvilCorp documentation, there is no such event type
    return S_OK;
}

HRESULT CMFSourceReaderCallback::OnReadSample(
    HRESULT hrStatus,
    DWORD dwStreamIndex,
    DWORD dwStreamFlags,
    LONGLONG llTimestamp,
    IMFSample *pSample)
{
    bool isGrabbing = false;
    try
    {
        if (SUCCEEDED(hrStatus))
        {
            if (pSample)
            {
                // Do something with the sample.
                IMFMediaBuffer * pMediaBuffer;
                HRESULT hr;
                hr = pSample->ConvertToContiguousBuffer(&pMediaBuffer);

                if (FAILED(hr))
                {
                   // Inform other thread of the disconnection
                   //...
                   return S_OK;
                }
                byte *imgBuff;
                DWORD buffCurrLen = 0;
                DWORD buffMaxLen = 0;
                pMediaBuffer->Lock(&imgBuff, &buffMaxLen, &buffCurrLen);

                // Process image byte buffer
                pMediaBuffer->Unlock();
                pMediaBuffer->Release();
            }
        }
        else
        {
            // Inform other thread of the disconnection
            //...
            return S_OK;
        }

        if ((MF_SOURCE_READERF_ENDOFSTREAM & dwStreamFlags) ||
            (MF_SOURCE_READERF_ERROR & dwStreamFlags))
        {
            // Inform other thread of the disconnection
            //...
            return S_OK;
        }
    } catch (std::exception &ex )
    {
            // Inform other thread of the disconnection
            //...
            return S_OK;
    }

    // check if other thread has not requested a stop
    isGrabbing = ...;

    if (isGrabbing)
    {
        //Re-arm callback
        HRESULT hr = _dataStruct->Reader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 
                                0, NULL, NULL, NULL, NULL);

        if (FAILED(hr))
        {
            // Inform other thread of the disconnection
            //...
            return S_OK;
        }
    }

    return S_OK;
}

有没有一种方法可以通过 IMFSourceReader 获得此类通知,而无需时不时地使用 MFEnumDeviceSources 轮询可用设备,这可能很耗时...?

提前致谢!

这里解释了处理捕获设备丢失的推荐方法:Handling Video Device Loss

您需要注册设备通知:RegisterDeviceNotification。您需要一个 window 句柄 (HWND)。

在消息循环中,您将收到WM_DEVICECHANGE。您必须检查符号 link(是 USB 摄像头吗?)。

完成后,调用 UnregisterDeviceNotification。