Microsoft DirectX 8.1 (C++) |
Dynamic reconnection is a change to the topology of the graph. In order not to lose data, an application or filter that initiates dynamic reconnection must be careful about the sequence of events. The section of the graph being reconfigured must not have any media data flowing through it. For example, suppose that an application dynamically replaces Filter 2 in the following filter graph.
To safely remove this filter and reconnect the graph, the application must perform the following steps:
Three interfaces support these operations:
The following sections describe the process in greater detail:
To block the data flow, call IPinFlowControl::Block on the upstream output pin (pin A). You can call this method either asynchronously or synchronously.
Asynchronously: Call the CreateEvent function to create an event object and pass the event handle to the Block method. The method returns immediately, and the pin signals the event when the operation has completed. Call a wait function such as WaitForSingleObject to wait for the event, as shown in the following code:
HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
pFlowControl->Block(AM_PIN_FLOW_CONTROL_BLOCK, hEvent);
WaitForSingleObject(hEvent, dwMilliseconds);
Synchronously: Pass NULL instead of an event handle. The method does not return until the operation completes. This might not happen until the pin is ready to deliver a sample; and if the filter is paused, the method might block indefinitely. Therefore, do not call Block synchronously from your main application thread.
After the graph is reconfigured, unblock the data flow by calling IPinFlowControl::Block with a value of zero for the first parameter.
If an upstream filter initiates the reconnection, it might be able to control the data flow internally, rather than by calling IPinFlowControl::Block.
By default, the filter graph manager automatically pushes data through the graph when you call the IGraphConfig::Reconnect method, which is described in the next section. However, if you do not use this methodfor example, if you use the IGraphConfig::Reconfigure methodyou must handle this operation yourself. In any case, it is useful to understand the process.
To push the data through the graph, perform the following steps:
To reconfigure the graph, call the IGraphConfig::Reconnect method. This method performs the following actions:
If the IGraphConfig::Reconnect method is not suitable for some reason, you can reconfigure the graph in a callback method. Implement the IGraphConfigCallback interface, and then call the IGraphConfig::Reconfigure method, which calls your callback method. In that case, you are responsible for pushing the data through the filter graph. Call the IGraphConfig::PushThroughData method.
The following example shows an outline of how an application might insert an effect filter, pointed to by the variable pFX, between a source filter and a renderer filter. Other scenarios are possible, and the IGraphConfig::Reconnect method takes several parameters that control its behavior. See the IGraphConfig reference for more information.
// Assume the graph is running.
IGraphConfig *pConfig;
pGraph->QueryInterface(IID_IGraphConfig, (void **)&pConfig);
// Block the data flow.
IPinFlowControl *pFlowControl;
pOutPin->QueryInterface(IID_IPinFlowControl, (void **)&pFlowControl);
pFlowControl->Block(AM_PIN_FLOW_CONTROL_BLOCK, NULL);
// Reconfigure the graph.
pGraph->AddFilter(pFX, L"Effect Filter");
pConfig->Reconnect(
pOutPin, // Start from this output pin.
NULL, // Search downstream for a suitable input pin.
NULL, // First connection is unspecified.
pFX, // Use this filter.
NULL,
0);
pFlowControl->Block(0, NULL); // Unblock the data flow.
Note pOutPin is assumed to be a pointer to an output pin on the source filter. For information on retrieving pointers to pins on a filter, see Enumerating Pins.
If dynamic reconnection is performed by a filter, rather than an application, there are potential threading issues. Specifically, if another process tries to stop the filter, it can deadlock while the graph waits for the filter to stop, and the filter waits for data to be pushed through the graph. To prevent this situation, some methods described previously take a handle to an event, which the filter should signal if it receives a call to its IMediaFilter::Stop method. For more information, see IGraphConfig and IPinConnection.