AddSourceFilterForMoniker() locks up sometimes.
From: Brian Stone (no.more.spam_at_stoneentertainment.com)
Date: 18 Jun 2004 20:20:07 -0700
I've coded a simple filter graph to capture frames from a video camera
via the Sample Grabber filter. To find the camera, I build the
enumated list of devices and pick the first one out of the list,
exactly as in Microsoft's source examples. I then add the camera
filter to the graph via AddSourceFilterForMoniker. However, sometimes
this function will lock up... like it's in a deadlock situtation or an
infinite loop. It simply stops and never returns.
My application works great when AddSourceFilterForMoniker returns
succesfully! I can grab frames from the Sample Grabber with no
problems at all. However, about half the time,
AddSourceFilterForMoniker just stops for no apparent reason, and the
program has to be restarted.
When I quit the program, I make sure to properly release all of the
filter interfaces and call CoUninitialize() in the same thread that
initialized the COM. I also check all errors from every function, and
everything appears to be S_OK. So... any ideas?
I've posted the relevent code below. This isn't the whole program,
but this is the exact series of code that is executed, starting at the
initialization of the COM up to the AddSourceFilterForMoniker()
A lot of this is Microsoft's own sample code from the MSDN website.
Thanks for any help!
DWORD g_dwGraphRegister = 0;
IMediaControl *g_pMC = NULL;
IMediaEventEx *g_pME = NULL;
IFilterGraph2 *g_pGraph = NULL;
ICaptureGraphBuilder2 *g_pCapture = NULL;
IBaseFilter *g_pGrabberFilter = NULL;
IBaseFilter *g_pNullFilter = NULL;
ISampleGrabber *g_pGrabberInterface = NULL;
// Initialize COM
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
// To capture video we have to build a DirectShow filter graph.
// The first step is to create a filter graph object.
// Create the filter graph object.
hr = CoCreateInstance (CLSID_FilterGraph, NULL, CLSCTX_INPROC,
IID_IFilterGraph2, (void **) &g_pGraph);
// Next, we'll create a capture graph builder.
hr = CoCreateInstance (CLSID_CaptureGraphBuilder2 , NULL,
CLSCTX_INPROC, IID_ICaptureGraphBuilder2, (void **) &g_pCapture);
// Create the filters that we will add to our filter graph.
// Create a sample grabber filter.
hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
// Create a null renderer filter. This filter will be attached to the
// pin of the sample grabber.
hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER,
// Next, get the required interfaces.
// We need to get the sample grabber filter's interface so we can
// that filter.
hr = g_pGrabberFilter->QueryInterface(IID_ISampleGrabber,
// We also need to get the Media Control interface for the filter
// need this to run the graph by calling the Run() method avaliable
// through this interface.
hr = g_pGraph->QueryInterface(IID_IMediaControl,(LPVOID *) &g_pMC);
// We also need to get the Media Event interface for the filter graph.
// This interface has the WaitForCompletion() method.
hr = g_pGraph->QueryInterface(IID_IMediaEvent, (LPVOID *) &g_pME);
// Set the window handle used to process graph events.
hr = g_pME->SetNotifyWindow((OAHWND)ghApp, WM_GRAPHNOTIFY, 0);
// Now is a good time to configure any filter interfaces we've
// We need to set the "media type" of the sample grabber filter. This
// pixel format of the filter's internal buffer. In this case, we
// request uncompressed 24-bit RGB image data.
mt.majortype = MEDIATYPE_Video; // Specify uncompressed video data.
mt.subtype = MEDIASUBTYPE_RGB24; // Specify 24-bit RGB pixel format.
hr = g_pGrabberInterface->SetMediaType(&mt);
// The sample grabber doesn't buffer data, by default. So, we need to
// to buffer the incoming video frames. The other way to capture
// be to create a callback function.
hr = g_pGrabberInterface->SetBufferSamples(TRUE);
// With the sample grabber filter set up as it is right now, we can
// current frame of video from the sample grabber by calling the
// GetCurrentBuffer method in the sample grabber interface object.
// first, we need to add the filters to the graph and then connect the
// Add the filters to the filter graph. Note... this doesn't create
// tree itself. It mearly makes the filters avaliable to the graph so
// construct the graph later on.
hr = g_pGraph->AddFilter(g_pGrabberFilter, L"Sample Grabber" );
hr = g_pGraph->AddFilter(g_pNullFilter, L"Null Renderer" );
// Before we can begin building the capture graph with the capture
// builder object, we need to find a video capture device connected to
// computer and get it's "moniker".
// Create a system device enumerator object.
CComPtr <ICreateDevEnum> pDevEnum = NULL;
hr = CoCreateInstance (CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
IID_ICreateDevEnum, (void ** ) &pDevEnum);
Msg(TEXT("Couldn't create system enumerator! hr=0x%x"), hr);
// Create an enumerator for the video capture devices.
CComPtr <IEnumMoniker> pClassEnum = NULL;
hr = pDevEnum->CreateClassEnumerator (CLSID_VideoInputDeviceCategory,
Msg(TEXT("Couldn't create class enumerator! hr=0x%x"), hr);
// If there are no enumerators for the requested type, then
// CreateClassEnumerator will succeed, but pClassEnum will be NULL.
if (pClassEnum == NULL)
MessageBox(ghApp,TEXT("No video capture device was
TEXT("This sample requires a video capture device, such as a USB
TEXT("to be installed and working properly. The sample will now
TEXT("No Video Capture Hardware"), MB_OK | MB_ICONINFORMATION);
// Use the first video capture device on the device list.
// Note that if the Next() call succeeds but there are no monikers,
// it will return S_FALSE (which is not a failure). Therefore, we
// check that the return code is S_OK instead of using SUCCEEDED()
if (S_OK != (pClassEnum->Next (1, &pMoniker, &cFetched)))
Msg(TEXT("Unable to access a video capture device!"));
// Finally... we're not done yet... but finally, we can start to build
// filter graph. The first object you always have to connect in a
// graph is a video source. In this case, the video source is the
// capture device that we just found. We can call the
// AddSourceFilterFromMoniker method in the filter graph object to
// automiatically choose the appropriate source filter for the device
// found and add that filter to the filter graph. Again, this doesn't
// the filter's input or output pins to anything, it just adds the
// the graph.
// Get the display name of the moniker
hr = pMoniker->GetDisplayName(NULL, NULL, &strMonikerName);
Msg(TEXT("Couldn't get moniker's display name! hr=0x%x"), hr);
// Create a bind context needed for working with the moniker
hr = CreateBindCtx(0, &pContext);
Msg(TEXT("Couldn't create a bind context for moniker! hr=0x%x"),
hr = g_pGraph->AddSourceFilterForMoniker(pMoniker, pContext,
Msg(TEXT("Failed in AddSourceFilterForMoniker()! hr=0x%x"), hr);
At this point AddSourceFilterForMoniker() will sometimes lock up,
and sometimes it will return properly. It locks up about half the
time. When that happens I have to restart the program and try
again. Sometimes it takes three or four restarts of the application
to get it to work. I don't have a clue why this happens. Any and
all help to solve this problem is greatly appreciated.