3.5 Events in DirectShow This section mainly describes how the events occur in DirectShow Filter Graphs and how the application receives event notification and responds to them.
3.5.1 Overview A FILTER notifies the Filter Graph Manager for an event to eventually happen. These events can be some predictive events such as flow end events, or some abnormalities fail to fail when render flow. A part of the event is handled by Filter Graph Manager, and the other part is processed by the application. If Filter Graph Manager does not deal with an event, then this event will be placed in the queue. Filter Graph can also send your own events to your application via queues.
The application receives events from the queue and responds to their type. Events in DirectShow are not shown in the message queue mechanism for Windows. The application allows the Filter Graph Manager to cancel the default operation of the specified event type, but put them in the event queue by the application to handle them.
Due to this mechanism, we can do it:
* Filter Graph Manager and the application's conversation
* FILTER can be and the application also talk to the Filter Graph Manager
* The application is determined to process the complexity of the handling event.
3.5.2 Accessing the event from the queue FILTER GRAPH Manager exposes interfaces that support event notifications: * iMediaEventsink Contains methods for Filter Send Event * iMediaEvent Method with Applications * iMediaEventEx inherits the extension IMEDIAEVENT interface Filter by Filter Graph Manager Call the iMediaEventsink :: Notify method to send event notices, one event notification consists of a parameter that represents the event type, and two DWORD types to place additional information. By the event number, these two parameters can be pointers, return values, reference times, or other information. Complete event number and parameter list, see Event Notification Codes (http://msdn.microsoft.com/library/en-us/directshow/HTM/EventNotificationCodes.asp). To take an event from an event queue, the application needs to call the iMediaEvent :: getEvent event on Filter Graph Manager. This method has been blocked until the event or timeout. Once an event is in the queue, this method returns an event number and two event parameters. After calling getEvent, the application should always call the iMediaEvent :: FreeEthtParams method to release all resources associated with the event parameters. For example, a parameter may be a BSTR value allocated by Filter Graph. The following code is a framework that takes an event from the queue:
Long Evcode, PARAM1, PARAM2; HRESULT HR; While (HR = Pevent-> GetEvent (& Evcode, & param1, & param2, 0), succeeded (hr)) {switch (evcode) {// call application-defined functions for each // TYPE OF Event That You Want to Handle.} HR = Pevent-> FreeEEventParams (Evcode, Param1, Param2);
To reset the Filter Graph Manager default event handler, call the iMediaEvent :: CanceldefaultHandling method, do parameters with the event number. You can restore an event's processing by calling the iMediaEvent :: RestoreFaultHandling method. If Filter Graph does not have a default process for an event number, call the above two methods do not produce any impact. 3.5.3 When the event occurs, the DirectShow event is handled, the application needs a way to know when the event is waiting in the queue. Filter Graph Manager provides two methods: * Window Notice: Once there is an event, Filter Graph Manager sends a user-defined window message to notify the application window * Event signal: If there is a DirectShow event in the queue, Filter Graph Manager triggered A Windows event, if the queue is empty, RESET event. Applications can use any way, but usually the window notification method is relatively simple. Window Notice: To set up a window notification, call the iMediaeventEx :: setNotifyWindow method and specify a private message, private message can be any of WM_APP to 0xBFFF. Once Filter Graph Manager puts a new event advertisement into the queue, it sends this message to the specified window. The application responds to this message from the message loop of the window. Here's how to set an example of a notification window:
#define WM_GraphNotify WM_APP 1 // Private Message. Pevent-> setNotifyWindow (OAHWND) G_HWND, WM_GRAPHNOTIFY, 0);
The message is a normal Windows message and is sent independently of the DirectShow message warning queue. The benefits of using this method are that most applications have a message loop, so I want to know when the DirectShow event does not have additional work. Below is a frame code that responds to the advertisement message:
LRESULT CALLBACK WindowProc (HWND hwnd, UINT msg, UINT wParam, LONG lParam) {switch (msg) {case WM_GRAPHNOTIFY:. HandleEvent (); // Application-defined function break; // Handle other Windows messages here too} return (. DefWindowProc (HWND, MSG, WPARAM, LPARAM);
Because event notices are asynchronously based on event notices, there are multiple events in the queue in the application response event. When the event becomes illegal, they will be removed from the queue. So in your event handling code, call getEvent until a failure code indicating the queue has been empty. Before the iMediaEventex pointer is released, call the setNotifyWindow method with the NULL parameter to cancel the event announcement. And in your event processing code, check if the IMEDIAEventEx pointer is legal before calling getEvent. These steps can prevent the application to continue receiving an error error after the iMediaEventEx pointer is released. Event signal: Filter Graph Manager establishes a manual-reset evenet that reflects the status of the event queue. If the queue contains unprocessed event notices, Filter Graph Manager will signal the manual reset event. If the queue is empty, call the iMediaEvent :: getEvent method to reset the (reset) event. Applications can determine the status of the queue through this event. Note: The terms here may be confused. Hand-reset event is an event type created by Windows's CreateEvent function, which is independent of the event defined by DirectShow. Call the iMediaEvent :: getEventHandle method to get the handle of the manual reset event, call a function such as WaitFormultiPleObjects to wait for the signal sent to the manual reset. Once the signal is received, you can call iMediaEvent :: getEvent to receive the DirectShow event. The following code illustrates this method. After obtaining the event handle, wait for the signal sent to the manual reset in 100 milliseconds, if there is a signal, it calls getEvent and print out the event number and event parameters on the Windows console, and loops in the EC_COMPLETE event. After the end, this marks the end of playback. Handle HEVENT; long evcode, param1, param2; boolean bdone = false; hRESULT HR = S_OK; hr = pevent-> getEventHandle (OAEvent *) & hevent); if (Failed (HR) {/ * Insert Failure-Handling Code Here. * /} While (!!_Object_0 == WaitForsingleObject (HEILENT, 100)) {whilevent (HR = pevent-> getEvent (& Evcode, & param1, & param2, 0), succeeded (hr)) {printf ("Event) Code:% # 04x / n params:% D,% D / N ", Evcode, Param1, Param2; Pevent-> FreeEventParams (Evcode, Param1, Param2); BDONE = (EC_COMPLETE == EVCODE);}}}