Overview of the Filter Connection Process (Windows CE 5.0)
Before two filters can be connected, they must each be added to the filter graph. When building a filter graph using Intelligent Connect (such as within a call to IMediaControl::RenderFile), the filter graph manager adds filters to the graph based on the media type in the file it has been given to render. The Graph Builder objects build specific types of graphs by selecting a predetermined arrangement of filters. An application can also build a graph manually by instructing the filter graph manager to add specific filters. In any of these scenarios, the filter is added to the graph by the IFilterGraph::AddFilter method, and the filter is notified that it has joined the graph by a call to the IBaseFilter::JoinFilterGraph method. The added filter can then be connected to the filters upstream and/or downstream from it. To initiate the connection process, the filter graph manager requests the filters to enumerate their pins and then, for each connection required, requests that an output pin connect to an input pin by calling the output pin's IPin::Connect method. All the details of the connection are then negotiated by the two pins within the scope of Connect.
To say that two filters are "connected" means that they have agreed on the media type of the data that will pass between them, and the size and location of the shared data buffers. The connection type is closely related to the transport type. There are different types of transport depending on whether the data is being "pushed" or "pulled" and whether the data buffers are located in main memory or on a hardware device.
The connection/transport type discussed here is an IMemInputPin connection, in which the buffers are allocated from main memory and the data is "pushed" into the buffer from the upstream pin. The base classes handle much of this connection mechanism. However, it is important to understand the connection process when writing a filter so that you can identify what to override and what is expected of your filter. Before two connected filters are prepared to pass media between them, the following connection and negotiation processes must occur in this order.
- The initial pin connection occurs.
- The output pin of one filter retrieves interfaces from the connected input pin.
- Both pins negotiate for a common media type.
- Both pins negotiate for an appropriate transport to pass the media.
In the first step, the filter graph manager informs the output pin of the upstream filter to connect to a specified input pin of the downstream filter. This results in an exchange of IPin interface pointers. Filters should never connect to other filters by themselves. The filter graph manager must always be the agent that initiates a connection, because deadlocks can occur otherwise. A filter or an application can instruct the filter graph manager to connect two pins (through the IGraphBuilder::Connect or IFilterGraph::ConnectDirect method), or the filter graph manager can determine to connect filters when rendering a filter by using the IGraphBuilder::Render or IGraphBuilder::RenderFile method.
In the second step, the output pin may request the IMemInputPin interface from the connected input pin. This is in preparation for the fourth step, where the output pin will use IMemInputPin to retrieve a memory allocator from the input pin. If the output pin already has a memory allocator (or some other transport in the case of hardware filters), it can skip this step or can request some other interface in a proprietary design.
In the third step, media types are tried until one is found that is acceptable to both pins or the pins run out of types to try (in which case the connection fails). First, the output pin asks the connected input pin to propose its list of media types. If none of these are acceptable to the output pin, the output pin proposes its own types.
In the fourth step, the output pin asks the connected input pin for an interface to a memory allocator object. In the base classes, these objects are implemented by CBaseAllocator and CMemAllocator. These objects create the media samples and their associated data buffers that each pin will access to transfer the multimedia data. If the output pin does not accept the input pin's allocator (for reasons discussed below), it can propose its own allocator. In either case it must notify the input pin of the selection.
Send Feedback on this topic to the authors