Direct Show 驱动摄像头,棘手(高手进)
我用DirectShow进行对摄像头的驱动遇到一个问题,假如PC机上有摄像头A、摄像头B、摄像头C,摄像头A被其他应用程序给占用了,其他两个摄像头处于闲置的状态,我的程序功能是开打一个可用的摄像头,根据日志,程序对于设备的遍历顺序是A->B->C,发现B始终无法成功打开,C可以成功被使用。可以保证所有的设备都是正常的,并且当PC机上只存在单独摄像头的时候,都是可以正常工作的。
我找不到原因来解决上述问题,检查代码并没有发现什么问题。
代码如下:
BOOL CCameraDS::CameraOpenUsable()
{
if ( m_enable )
{
return m_enable;
}
int num = 0;
CComPtr<ICreateDevEnum> pCreateDevEnum;
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum, (void**)&pCreateDevEnum);
if ( hr != S_OK )
{
return m_enable;
}
CComPtr<IEnumMoniker> pEm;
hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEm, 0);
if ( hr != S_OK )
{
return m_enable;
}
ULONG cFetched;
IMoniker* pM = NULL;
pEm->Reset();
IPropertyBag* pPropBag = NULL;
while( pEm->Next(1, &pM, &cFetched) == S_OK )
{
num++;
SAFE_RELEASE( pPropBag );
hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPropBag );
if ( SUCCEEDED(hr) )
{
CameraResRelease();
hr = pM->BindToObject(0, 0, IID_IBaseFilter, (void **)&m_sourceBaseFilter);
if ( FAILED(hr) )
{
continue;
}
if ( !CameraResInitialize() )
{
continue;
}
else if ( !CameraSetMediaType() )
{
continue;
}
else if ( !CameraRun() )
{
continue;
}
m_enable = TRUE;
break;//找到一个可以成功打开使用的摄像头,退出。
}
}
SAFE_RELEASE( pPropBag );
SAFE_RELEASE( pM );
return m_enable;
}
BOOL CCameraDS::CameraResInitialize()
{
BOOL ret = FALSE;
HRESULT hresult;
hresult = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&m_graphBuilder);
if (FAILED(hresult))
{
goto exit;
}
hresult = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&m_captureGraphBuilder2);
if (FAILED(hresult))
{
goto exit;
}
hresult = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&m_sampleGrabberBaseFilter);
if (FAILED(hresult))
{
goto exit;
}
hresult = m_sampleGrabberBaseFilter->QueryInterface(IID_ISampleGrabber, (void **)&m_sampleGrabber);
if (FAILED(hresult))
{
goto exit;
}
hresult = m_graphBuilder->QueryInterface(IID_IMediaControl, (void **)&m_mediaControl);
if (FAILED(hresult))
{
goto exit;
}
hresult = m_captureGraphBuilder2->SetFiltergraph(m_graphBuilder);
if (FAILED(hresult))
{
goto exit;
}
hresult = m_graphBuilder->AddFilter(m_sourceBaseFilter, L"Video Capture");
if (FAILED(hresult))
{
goto exit;
}
hresult = m_graphBuilder->AddFilter(m_sampleGrabberBaseFilter, L"Sample Grabber");
if (FAILED(hresult))
{
goto exit;
}
hresult = m_sampleGrabber->SetBufferSamples(TRUE);
if (FAILED(hresult))
{
goto exit;
}
hresult = m_sampleGrabber->SetOneShot(FALSE);
if (FAILED(hresult))
{
goto exit;
}
m_sampleGrabberCallback = new SampleGrabberCallback( this );
if (m_sampleGrabberCallback == NULL)
{
goto exit;
}
hresult = m_sampleGrabber->SetCallback(m_sampleGrabberCallback, 1);
if (FAILED(hresult))
{
goto exit;
}
ret = TRUE;
exit:
return ret;
}
BOOL CCameraDS::CameraSetMediaType()
{
BOOL ret = FALSE;
HRESULT hresult;
AM_MEDIA_TYPE am_media_type;
ZeroMemory(&am_media_type, sizeof(am_media_type));
am_media_type.majortype = MEDIATYPE_Video;
am_media_type.subtype = MEDIASUBTYPE_RGB32;
am_media_type.formattype = FORMAT_VideoInfo;
hresult = m_sampleGrabber->SetMediaType(&am_media_type);
if (FAILED(hresult))
{
goto exit;
}
hresult = m_captureGraphBuilder2->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, m_sourceBaseFilter, NULL, m_sampleGrabberBaseFilter);
if (FAILED(hresult))
{
goto exit;
}
ZeroMemory(&am_media_type, sizeof(am_media_type));
hresult = m_sampleGrabber->GetConnectedMediaType(&am_media_type);
if (FAILED(hresult))
{
goto exit;
}
ret = TRUE;
exit:
return ret;
}
BOOL CCameraDS::CameraRun()
{
BOOL ret = FALSE;
if ( m_mediaControl )
{
HRESULT hresult = m_mediaControl->Run();//打开摄像头A,B,Run 失败
if ( SUCCEEDED(hresult) )
{
ret = TRUE;
}
}
return ret;
}
希望某位高人可以指点一二,感激不尽!!!