Building Filter Graphs
When an application wants to play back a media file, it will create an instance of the filter graph manager and then ask it to 'RenderFile' giving it a file name or URL. The graph manager will then build a graph of filters to play back that file. Your application can also build or modify graphs itself, or use the Capture Graph Builder or DVD Graph Builder to build graphs for specific tasks. There is also a visual Graph Editor tool in the sdk which you can use to insert and connect specific filters (and a Windows mobile version here).
When you call RenderFile, the FG manager starts by selecting a source filter for the file you pass in. It does this using a table in the registry that contains sets of offset, mask and test bytes to check the file. This gives it the CLSID of a filter to use as a source filter (and also a media type for the file to save the source filter redoing the check). See 'Registering a custom file type' in the DirectShow documentation.
It then renders each output pin from the source filter. It does this by trying to connect up each possible filter. If it connects, it will then try to render the output pins from that newly connected filter by the same process. A limit on the depth of the tree prevents it from just going on indefinitely -- after (I think) 5 steps, if it hasn't rendered the pin it will give up, go back up and try a different filter). Only the merit value (see below) prevents every graph being filled with endless null filters. When connecting up a filter, it uses QueryInternalConnections to work out which output pins it now needs to render.
The filters that it tries to connect are: all those in the graph that have free input pins, and those in the registry. It tries any filter in the graph before instantiating new filters. This makes it easy to add your own filter (simply put it in the graph before calling RenderFile, assuming that the media types are specific enough that it will only get used in the place you want it to be used). Also this means that if you have a filter that renders both audio and video, you can be sure that once your filter is connected up for the video stream, the graph will try to use your filter for the audio too.
It will only try filters from the registry if they are registered as taking the right media type and subtype. Each filter in the registry has a merit value, and filters will be tried in order of merit (MERIT_DO_NOT_USE and below are not tried). You can register your filter as having a wild-card input (GUID_NULL as a media type or as a subtype). Your filter can also register its output pins: I don't think this is important for rendering, but it is needed for a 'Connect' operation to try your filter. Also note that the information in the registry is only used to prevent loading filters unnecessarily. Once a filter has been loaded, the media type information is always obtained from the pin and not from the registry.
RenderFile will only return S_OK if all the output pins from the chosen source filter are fully rendered (according to QueryInternalConnections). If it fails to achieve this, but it can render some of the outputs, it will go back to its 'best-so-far' graph and return a success code that is not S_OK. The best-so-far is the one that renders the highest proportion of output pins with the fewest filters.