使用 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。
我正在使用 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。