|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.|
When a filter's input pin receives a sample, the filter processes the data in the sample and then delivers the sample to the next downstream filter. As the previous section described, the filter can do all of its processing while inside the IMemInputPin::Receiveon the downstream input pin, passing it a pointer to the sample's method, or it can hold the sample and process it afterward.
Within the call to Receive, the input pin has the option of blocking the upstream filter's calling thread. You can query the input pin's behavior by calling the IMemInputPin::ReceiveCanBlockmethod. If the return value is S_OK, the pin might block on a call to Receive. If the return value is S_FALSE, the pin will never block on calls to Receive. Based on the return value, the upstream filter might use a separate worker thread to deliver samples.
Some filters process samples in place, without copying any data. Other filters copy the data before processing it. Obviously, it is better to process samples in place whenever possible, to avoid the overhead of unneeded copy operations.
The input pin can reject samples by returning an error code or S_FALSE in its Receivemethod. The value S_FALSE indicates that the pin is flushing data (see "Flushing" below). An error code indicates some other problem. For example, if the filter is stopped, the return value is VFW_E_WRONG_STATE. If a pin rejects a sample, the upstream filter calls the IPin::EndOfStreammethod and stops sending data. If the pin returned an error code, the upstream filter also signals EC_ERRORABORT to the filter graph manager.
The upstream filter must serialize all of its Receivecalls to a given input pin.
When a source filter has no more data to send, it calls the IPin::EndOfStreammethod on the downstream input pin. The downstream filter propagates the call to the next filter. Eventually the EndOfStreamcall reaches the renderer filter. The renderer filter signals EC_COMPLETE to the filter graph manager.
Before posting an EC_COMPLETE notification to the application, the filter graph manager waits until all the streams signal EC_COMPLETE. The application does not receive an EC_COMPLETE notice until all the streams have completed. To determine the number of streams in the graph, the filter graph manager counts the number of filters that support IMediaSeekingor IMediaPositionand have a rendered input pin. A rendered input pin is an input pin with no corresponding outputs. The IPin::QueryInternalConnectionsmethod returns zero for a rendered input pin.
Filters must serialize EndOfStreamcalls with IMemInputPin::Receivecalls.
Flushing is the process of discarding all the pending samples in the graph. Flushing enables the graph to be more responsive when events alter the normal data flow. For example, in a seek operation, pending data is flushed from the graph before new data is introduced. If the graph contains multiple streams, it is possible to flush individual streams separately.
Flushing is a two-stage process:
When the BeginFlushmethod is called on a filter's input pin, the filter performs the following actions:
When the EndFlushmethod is called, the filter performs the following actions:
At this point, the filter can accept samples again.
In the pull model, the parser filter initiates flushing rather than the source filter. The sequence of events is the same, except that the parser also calls BeginFlushand EndFlushon the source filter's output pin.
Because filter operations are multithreaded, it is crucial that a filter serialize certain operations. Otherwise, race conditions can result. For example, the filter might try to use an allocator that is already decommitted. Filters use two critical sections, one to hold a streaming lock and the other to hold a filter state lock.
The streaming lock serializes streaming operations. The filter holds this lock when it processes the following method calls:
The filter state lock serializes state changes. The filter holds this lock when it processes the following method calls:
Within the Stopand EndFlushmethods, the filter must synchronize its filter state with its streaming state. In the Stopmethod, the filter holds the filter state lock and decommits the input pin's allocator. Then it holds the streaming lock and decommits the output pin's allocator.
The following base classes are useful for implementing data flow in a filter.
|COutputQueue||Queues data to be delivered downstream. Uses a worker thread for delivering samples.|
|CPullPin||Input pin on a parser filter. Uses a worker thread to pull data from a source filter.|
|CSourceStream||Output pin on a source filter. Uses a worker thread to push data downstream.|
Last updated on Tuesday, May 18, 2004