Important:
This is retired content. This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This content may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.
A version of this page is also available for
4/8/2010

Despite its name, the Capture Graph Builder is useful for building many kinds of custom filter graphs, not only capture graphs. This topic provides a brief overview of how to use this object.

The Capture Graph Builder exposes the ICaptureGraphBuilder2 Interface. Start by calling CoCreateInstanceto create the Capture Graph Builder and the Filter Graph Manager. Then initialize the Capture Graph Builder by calling ICaptureGraphBuilder2::SetFiltergraphwith a pointer to the Filter Graph Manager, as shown in the following code:

Copy Code
IGraphBuilder *pGraph = NULL;
ICaptureGraphBuilder2 *pBuilder = NULL;

// Create the Filter Graph Manager.
HRESULT hr =  CoCreateInstance(CLSID_FilterGraph, NULL,
	CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);

if (SUCCEEDED(hr))
{
	// Create the Capture Graph Builder.
	hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
		CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2,
		(void **)&pBuilder);
	if (SUCCEEDED(hr))
	{
		pBuilder->SetFiltergraph(pGraph);
}
};

Connecting Filters

The ICaptureGraphBuilder2::RenderStreammethod connects two or three filters together in a chain. Generally, the method works best when each filter has no more than one input pin or output pin of the same type. This discussion begins by ignoring the first two parameters of ICaptureGraphBuilder2::RenderStreamand focusing on the last three parameters. The third parameter is an IUnknownpointer, which can specify either a filter (as an IBaseFilter Interfacepointer) or an output pin (as an IPin Interfacepointer). The fourth and fifth parameters specify IBaseFilterpointers. The ICaptureGraphBuilder2::RenderStreammethod connects all three filters in a chain. For example, suppose that A, B, and Care filters. Assume for now that each filter has exactly one input pin and one output pin. The following call connects A to B, and then B to C:

Copy Code
RenderStream(NULL, NULL, A, B, C)

All connections are "intelligent," meaning that additional filters are added to the graph as needed. For more information, see Graph Building with Intelligent Connect. To connect just two filters, set the middle value to NULL. For example, this call connects A to C:

Copy Code
RenderStream(NULL, NULL, A, NULL, C)

You can create longer chains by calling the method twice:

Copy Code
RenderStream(NULL, NULL, A, B, C)
RenderStream(NULL, NULL, C, D, E)

If the last parameter is NULL, the method automatically locates a default renderer. It uses the DirectShow Video Renderer Filterfor video and the Audio Renderer (WaveOut) Filterfor audio. Thus:

Copy Code
RenderStream(NULL, NULL, A, NULL, NULL)

is equivalent to

Copy Code
RenderStream(NULL, NULL, A, NULL, R)

where Ris the appropriate renderer.

If you specify a filter in the third parameter, rather than a pin, you may need to indicate which output pin should be used for the connection. That is the purpose of the method's first two parameters. The first parameter applies only to capture filters. It specifies a GUID that indicates a pin category. For a complete list of categories, see Pin Property Set. Two of the categories are valid for all capture filters:

  • PIN_CATEGORY_CAPTURE

  • PIN_CATEGORY_PREVIEW

If a capture filter does not supply separate pins for capture and preview, the ICaptureGraphBuilder2::RenderStreammethod inserts a Smart Tee Filter, which splits the stream into a capture stream and a preview stream. From the application's standpoint, you can simply treat all capture filters as having separate pins and ignore the underlying topology of the graph.

For file capture, connect the capture pin to a mux filter. For live preview, connect the preview pin to a renderer. If you switch the two categories, the graph might drop an excessive number of frames during the file capture; but if the graph is connected properly, it drops preview frames as needed in order to maintain throughput on the capture stream.

The following example shows how to connect both streams:

Copy Code
// Capture to file:
pBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, NULL,
pCapFilter, NULL,
pMux);
// Preview:
pBuilder->RenderStream(&PIN_CATEGORY_PREVIEW, NULL,
pCapFilter, NULL, NULL);

Some capture filters also support closed captions, indicated by PIN_CATEGORY_VBI. To capture the closed captions to a file, render this category to the mux filter. To view the closed captions in your preview window, connect to the renderer:

Copy Code
// Capture to file:
pBuilder->RenderStream(&PIN_CATEGORY_VBI, NULL, pCapFilter,
NULL, pMux);
// Preview on screen:
pBuilder->RenderStream(&PIN_CATEGORY_VBI, NULL, pCapFilter,
NULL, NULL);

The second parameter to ICaptureGraphBuilder2::RenderFileidentifies the media type, and is typically one of the following:

  • MEDIATYPE_Audio

  • MEDIATYPE_Video

  • MEDIATYPE_Interleaved (DV)

You can use this parameter whenever the filter's output pins support the enumeration of preferred media types. For file sources, the Capture Graph Builder automatically adds a parser filter if needed, and then queries the media types on the parser. Also, if the last filter in the chain has several input pins, the method attempts to enumerate their media types. However, not all filters support this functionality.

Finding Interfaces on Filters and Pins

After you build a graph, you will typically need to locate various interfaces exposed by filters and pins in the graph.

The simplest way to find an interface is to use the ICaptureGraphBuilder2::FindInterfacemethod. This method walks the graph (filters and pins) until it locates the desired interface. You can specify the starting point for the search, and you can limit the search to filters upstream or downstream from the starting point.

The following example searches for the IAMStreamConfig Interfaceon a video preview pin:

Copy Code
IAMStreamConfig *pConfig = NULL;
HRESULT hr = pBuild->FindInterface(
	&PIN_CATEGORY_PREVIEW,
	&MEDIATYPE_Video,
	pVCap,
	IID_IAMStreamConfig,
	(void**)&pConfig
);
if (SUCCESSFUL(hr))
{
	/* ... */
	pConfig->Release();
}

Finding Pins

Less commonly, you may need to locate an individual pin on a filter, although in most cases the ICaptureGraphBuilder2::RenderStreamand ICaptureGraphBuilder2::FindInterfacemethods will save you the trouble. If you do need to find a particular pin on a filter, the ICaptureGraphBuilder2::FindPinhelper method is useful. Specify the category, the media type (video or audio), the direction, and whether the pin must be unconnected.

For example, the following code searches for an unconnected video preview pin on a capture filter:

Copy Code
IPin *pPin = NULL;
hr = pBuild->FindPin(
	pCap, 			 // Pointer to the filter to search.
	PINDIR_OUTPUT, 	// Search for an output pin.
	&PIN_CATEGORY_PREVIEW,  // Search for a preview pin.
	&MEDIATYPE_Video,  // Search for a video pin.
	TRUE, 			 // The pin must be unconnected. 
	0, 				// Return the first matching pin (index
0).
	&pPin); 			 // This variable receives the IPin
pointer.
if (SUCCESSFUL(hr))
{
	/* ... */
	pPin->Release();
}

See Also

Concepts

Video Capture