DirectShow Technical Description & Applications (3) - Continued

zhaozj2021-02-16  55

Filter State (Filter State)

There are three states of filters: stopped, paused and running. This paused status can respond immediately to the running command. In DirectShow is made by the Filter Table Manager to control all state changes. When the application calls iMediaControl :: Run, iMediaControl :: Pause, the filter table manager changes the status of all filters with the appropriate methods in all filter's IMEDIAFILTER interfaces. The stopped state and the conversion between the running status will always pass through the paused state. So, if the table is in a stopped state, when the application starts the table, the filter table manager will first turn the table in the paused state, and then transfer from the paused state to being running.

In most filters, running status and paused status are the same. Consider the following filter table:

Source> Transform> Renderer

Assume that the current source filter is not a real-time capture source. When the source filter is paused, it creates a thread to generate new data and write it quickly into the media sample. This thread gives the media sample PUSH downstream filters through the Imeminputpin :: Receive method. Convert filters Receive media samples from source filter threads. It can also use the working thread to process the media sample and pass to the restored filter, but it is usually not another thread to process data. When the reduced filter is in a paused state, it will wait for a media sample. When it accepts a media sample, it does not necessarily block it or saves it. If it is a video restore device, it will restore the data as an image, because only one media sample is accepted, then this image is still, like a big poster. If the table is paused, the media sample will be put on the first media sample of the table, and each filter will be blocked in Receive or GetBuffer. Although there will be no data is lost, once the source thread is canceled, it will start from the blocked place.

The source filter and conversion filter can ignore the conversion process of the suspended state to the running state, which will immediately restore the work of processing data very quickly. However, when the restore device operates, it starts to restore the media sample. First it restores the media sample that it saved during the pause. Whenever a restore device receives a new media sample, it calculates the presentation time of this media sample. The restore device is saved for each media sample before the currently restored media samples. When it waits time, it either blocks in the Receive method, or accepts a new media sample in the queue in the working thread. The filter of the filter upstream of the restore device does not participate in timing.

Real-time source, such as capture equipment, is an exception of a general structural system. For a real-time source, it is not suitable for pre-providing any data. The application can pause the filter table, and then wait for a long time when starting it again. The table should not process "old" media samples. Therefore, the time source does not produce a sample during pause, and only occurs at runtime. In order to send this behavior information to the filter table manager. The iMediafilter :: getState method of the source filter will return to VFW_S_CANT_CUE. This constant indicates that although the restore device does not receive any data, the filter is already suspended.

When the filter is stopped, it will refuse any pass to it. Subsequently, the source filter closes its stream processing thread, and the other filters turn off the working thread it established. The needles are released to the dispenser.

State change

The filter table manager is completely changed in the order of the following swaps, which starts at the restorizer and ends on the source filter. This order can prevent the loss of the sample and the deadlock of the table. In the change in state, the conversion between the paused state and the stop state is critical.

Stop until pause: After each filter enters pause, they all entered the status of the media sample. The source filter is still the last one for pause. It creates a stream processing thread and starting the media sample. Because all downstream filters are paused, there is no filter reject the sample. When the restore device in each table receives a sample, the status change of the filter table manager is completed. (Real-time source filter is an exception, it has been discussed.) Pause to stop: After the filter is stopped, it releases the media sample held by (Holds), which can unope the upstream filter in GetBuffer Waiting. If you enter the stop, the filter is waiting for resources in the Receive method, then it will stop waiting and returning from Receive because its downstream filter is already paused, downstream filter unconditionally ending the Receive method. Therefore, when the filter table manager stops the next upstream filter, that filter has been unlocked from getBuffer and Receive to respond to the stop command. The upstream filter may deliver some media samples before it gets the stop command, but the downstream filter will reject it directly because the downstream filter is already in a stopped state.

PULL mode

In the IMEMINPUTPIN interface, it is determined by the upstream filter to determine what data is to send, and it gives the data PUSH to the downstream filter. However, in some filters, it is suitable for use in PULL mode. In this mode, the downstream filter requests data to the upward filter. The media sample is still from the output needle to the input pin to reach the downstream filter, and the difference is that the flow of data by the downstream filter. This connection should use the IASYNCReader interface.

The typical use for the pull model is in file playback. For example, in an AVI playback graph, the Async File Source filter performs generic file reading operations and delivers the data as a byte stream, with no format information. The AVI Splitter filter reads the AVI headers and parses the stream into video and audio samples. The AVI Splitter can determine what data it needs better than the Async File Source filter, and therefore it uses IAsyncReader instead of IMemInputPin.

File playback is a relatively typical PULL mode. For example, in an AVI play filter table, the ASYNC File source filter completes the read operation of the file and generates a byte stream without any format information. AVI Decomposes the filter reads the AVI data header and analyzes the stream into audio streams and video streams. The AVI Decomposing filter can determine the data it needs to be read because it uses the IASYNCReader interface instead of the IMEMEINPUTPIN interface.

In order to be able to request data to the output needle, the input needle uses the following methods:

IASYNCREADER :: REQUEST

IASYNCREADER :: SyncRead

IASYNCREADER :: SyncReadalIgned.

The first method is asynchronous to support multiple overlap reads. Other methods are synchronous.

In theory, some filters can support IASYNCREADER, but in practice, it is designed for those source filters connected to decomposing filters. The behavior of the resolver is very similar to the source filter in the PUSH mode. When it is suspended, it creates a streaming thread from the PULL data from the IASYNCReader connection, and flows down the filter Push data. Its output needle uses the IMEMINPUTPIN interface, and other parts of the table are standard PUSH mode. Event notification in DirectShow

This section will describe how the event is implemented in the Microsoft® DirectShow® filter table; an application can accept event notification and respond to them.

Event notification overview

Filters communicate an event to the Filter Table Manager by delivering event notifications. The event can be any information, such as the end, or an error, such as the failure of the original stream. The filter table manager itself handles some filter events, and other events remain to the application for processing. If the Filter Table Manager encounters an incomplete event, it puts the event into a queue. Similarly, the filter table manager also puts its own event notification into the queue and processes in order to apply.

Applications can receive events from the queue and respond to them. Therefore, DirectShow's event notification is very similar to the Microsoft® Windows® message queue mode. The application can cancel the filter table manager itself can handle this behavior of the event, filter table management, putting these events into the queue and processed by the application. This mechanism allows:

Filter Table Manager communicates with the application.

Filters can communicate with applications and filter table management.

Determine which events are handled by the application.

Receive event

The Filter Table Manager exposes three interfaces to the outside to support event notifications.

IMediaEventSink contains methods for filter delivery events

IMediaEvent contains methods for application reception events

IMediaeventex inherits from and extends the iMediaEvent interface.

IMediaEventex inherits and expands the ImdeiAevent interface

The filter delivers event notifications by calling the IMEDIAEventsink :: Notify method of the Filter Table Manager. An event notification consists of an event code and two DWORD type parameters. According to different event code, the parameter value may be a pointer, return code, reference time, or other information.

In order to receive events from the queue, the application should call the iMediaEvent :: getEvent method to receive data. This method is blocked until an event or exceeds the time limit from a queue. When the getEvent is called, the application should always call the iMediaEvent :: FreeEventParams method to release resources in the event parameter. For example, parameters may be the BSTR string provided by the filter table.

The following code provides a framework for accepting events from the queue.

Long Evcode, Param1, Param2;

HRESULT HR;

While (hr = pevent-> getEvent (& Evcode, & param1, & param2, 0), succeededed (hr))

{

Switch (EVCode)

{

// Call Application-Defined Functions for Each

// Type of Event this You Want to Handle.

}

HR = pevent-> freeeeventparams (Evcode, Param1, Param2);

}

In order to stop the default processing of a filter table manager for an event, you can call the iMediaEvent :: CanceldefaultHandling method. You can restore the default processing of the event by calling the iMediaEvent :: RestorefaultHandling method. For events that do not have the default processing of the Filter Table Manager, call these methods will not have any impact. When did the event occur?

For the DirectShow event, the application needs a method that can be known when there is an event in the queue. Filter Table Manager provides two ways to achieve:

Window Notification: When a Filter Table Manager generates a new event, send a custom message to the application window.

Event signal: If there is a DirectShow event in the queue, the Filter Table Manager sends a window event. And reset the event in the queue.

An Application CAN Use Either Technique. Window Notification IS Usually Simpler.

Applications can be implemented using other techniques. But window messages are usually more simple.

Window notification

You can call the iMediaEventEx :: SetNotifyWindow method to specify a private message to create a window notification. This private message can use the number from WM_APP to WM_APP 0xBFFF. As long as the filter table management is placed in a new event to the queue, it sends information to the specified application window. The application responds to messages from a Windows message loop.

The following code illustrates how to set the notification window.

#define WM_GraphNotify WM_APP 1 // Private Message.

PEVENT-> SetNotifyWindow (OAHWND) G_hwnd, WM_GraphNotify, 0);

The following code shows how to respond to the window message

LResult Callback WindowProc (HWND HWND, UINT MSG, UINT WPARAM, long lparam)

{

Switch (msg)

{

Case WM_GRAPHNOTIFY:

HandleEvent (); // application definition function.

Break;

// You can also write message processing here.

}

Return (DEFWIndowProc (HWND, MSG, WPARAM, LPARAM);

}

Because event notifications and message loops are asynchronous, there may be multiple event messages when your application responds to messages. It may sometimes become invalid, then it will be cleared. Therefore, in your event handling code, you should call the getEvent method until the failure code is returned, that is, the message queue is empty.

Note that when you release the iMediaEventEx pointer, you will first cancel event notifications by passing an empty pointer to SetNotifyWindow. In your event handling code, a must check the validity of the IMEIAEventEx pointer before calling the getEvent method. This can prevent the application that may have an error that may occur again after the iMediaEventEx pointer is released.

Signal

Filter Table Manager maintains an event of manual-reset to react the status of the event queue. If the event queue contains unresolved event notifications, filter table management will send a manual reset event. If the event is empty, call the iMediaEvent :: getEvent method to reset the event. Applications can use this event to determine the status of the queue.

Note: This language may be misunderstood. Manual reset event is an event type established by the Windows CreateEvent function, which does not do anything in DirectShow.

Call the iMediaEvent :: getEventHandle method to get the handle of the manual reset event. You can wait for this event through the WaitFormultiPleObject function. Once this event occurs, you can get the DirectShood event when you call the iMediaEvent :: getEvent method. The following code example shows such a function. It acquires the handle of the event, waiting for the event of the event every 100 milliseconds. When the event occurs, the event is called by calling the getEvent method and the event code and event parameters are displayed. The cycle ends when the EC_COMPLETE event (which represents playback has been completed).

Handle HEVENT;

Long Evcode, Param1, Param2;

Boolean bdone = false;

HRESULT HR = S_OK;

HR = pevent-> getEventHandle ((OAEvent *) & hev);

While (! bdone)

{

IF (wait_Object_0 == WaitforsingleObject (HEVENT, 100))

{

While (hr = pevent-> getEvent (& Evcode, & param1, & param2, 0), succeededed (hr))

{

Printf ("Event Code:% # 04x / N Params:% D,% D / N", EVCODE, PARAM1, PARAM2;

HR = pevent-> freeeeventparams (Evcode, Param1, Param2);

BDONE = (EC_COMPLETE == EVCODE);

}

}

}

Because the filter table will automatically set or reset the event appropriately, your application can freely processes these things. Similarly, after you release the filter table, the filter table will release the event handle. Therefore, after you release the filter table, don't use the event handle.

(to be continued...)

转载请注明原文地址:https://www.9cbs.com/read-24708.html

New Post(0)