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

An end-of-stream notification begins at an upstream filter (such as the source filter) when that filter detects that it can send no more data. It is passed through every filter in the graph and ends at the renderer, which is responsible for subsequently sending an EC_COMPLETEnotification to the filter graph manager.

Renderers have special responsibilities when it comes to handling these notifications.

A renderer receives an end-of-stream notification when its input pin's IPin::EndOfStreammethod is called by the upstream filter.

A renderer should note this notification and continue to render any data it has already received.

After all remaining data is received, the renderer should send an EC_COMPLETEnotification to the filter graph manager. The EC_COMPLETEnotification should be sent only once by a renderer each time it reaches the end of a stream.

Further, EC_COMPLETEnotifications must never be sent except when the filter graph is running. Therefore, if the filter graph is paused when a source filter sends an end-of-stream notification, EC_COMPLETEshould not be sent until the filter graph is finally run.

Any calls to the IMemInputPin::Receiveor IMemInputPin::ReceiveMultiplemethods after an end-of-stream notification is signaled should be rejected.

E_UNEXPECTED is the most appropriate error message to return in this case.

When a filter graph is stopped, any cached end-of-stream notification should be cleared and not resent when next started. This is because the filter graph manager always pauses all filters just before running them so that proper flushing occurs.

So, for example, if the filter graph is paused and an end-of-stream notification is received, and then the filter graph is stopped, the renderer should not send an EC_COMPLETEnotification when it is subsequently run.

If no seeks have occurred, the source filter sends another end-of-stream notification during the pause state that precedes a run state.

If, on the other hand, a seek has occurred while the filter graph is stopped, the source filter might have data to send, so it will not send an end-of-stream notification.

Video renderers often depend on end-of-stream notifications for more than the sending of EC_COMPLETEnotifications. For example, if a stream has finished playing (that is, an end-of-stream notification is sent) and another window is dragged over a video renderer window, a number of WM_PAINT window messages will be generated.

The typical practice for running video renderers is to refrain from repainting the current frame upon receipt of WM_PAINT messages (based on the assumption that another frame to be drawn will be received). However, when the end-of-stream notification has been sent, the renderer is in a waiting state; it is still running but is aware that it will not receive any additional data. Under these circumstances, the renderer customarily draws the playback area black.

Handling flushing is an additional complication for renderers.

Flushing is carried out through a pair of IPinmethods called BeginFlushand EndFlush.

Flushing is essentially an additional state that the renderer must handle. It is illegal for a source filter to call BeginFlushwithout calling EndFlush, so hopefully the state is short and discrete; however, the renderer must correctly handle data or notifications it receives during the flush transition.

Any data received after calling BeginFlushshould be rejected immediately by returning E_UNEXPECTED. Further, any cached end-of-stream notification should also be cleared when a renderer is flushed.

A renderer is typically flushed in response to a seek. The flush ensures that old data is cleared from the filter graph before fresh samples are sent. (Typically, the playing of two sections of a stream, one after another, is best handled through deferred commands rather than waiting for one section to finish and then issuing a seek command.)