DirectShow开发快速入门之三 -- 事件通知机制
来源:互联网 发布:最火的网络直播平台 编辑:程序博客网 时间:2024/05/03 17:09
事件是Graph图和应用程序之间互相通信的机制,类似于消息机制。当某个事件发生时,比如数据流结束,产生一个错误等,Filter就要给Filter图表管理器(Graph Manager)发送一个事件通知。Filter图表管理器处理其中的一部分事件,将其他事件要交给应用程序处理。如果图表管理器没有处理一个filter事件,它就把事件通知放入到一个队列中,图表管理器也可以将自己的事件通知放进队列中。然后应用程序可以自己处理队列中的事件。DirectShow中的事件通知就和windows的消息机制差不多。Filter,图表管理器和应用程序通过这种机制就可以互相通信。
如何处理事件
Filter图表管理器暴露了三个接口用来处理事件通知
IMediaEventSink Filter用这个接口来post事件。
IMediaEvent 应用程序利用这个接口来从队列中查询消息
IMediaEventEx 是imediaevent的扩展。
Filter都是通过调用图表管理器的 IMediaEventSink::Notify方法来通知图表管理器某种事件发生。事件通知包括一个事件code,这个code不仅仅代表了事件的类型,还包含两个DWORD类型的参数用来传递一些其他的信息。
关于事件code的内容,在下面的一个专题中列出,这里暂略,使用时可以参考帮助。
应用程序通过调用图表管理器的IMediaEvent::GetEvent方法来从事件队列中获取事件。如果有事件发生,该函数就返回一个事件码和两个参数,如果没有事件,则一直阻塞直到有事件发生和超过某个时间。调用GetEvent函数后,应用程序必须调用IMediaEvent::FreeEventParams来释放事件码所带参数的资源。例如,某个参数可能是由filter graph分配的内存。
下面的代码演示了如何从事件队列中提取事件
long evCode, param1, param2;
HRESULT hr;
while (hr = pEvent->GetEvent(&evCode, ¶m1, ¶m2, 0), SUCCEEDED(hr))
{
switch(evCode)
{
// Call application-defined functions for each
// type of event that you want to handle.
}
hr = pEvent->FreeEventParams(evCode, param1, param2);
}
为了重载Filter图表管理器对事件的缺省处理,你可以使用某个事件码做参数调用IMediaEvent::CancelDefaultHandling ,这样就可以屏蔽图表管理器对某个事件码的处理了。如果要恢复图表管理器对该事件码的缺省处理,可以调用 IMediaEvent::RestoreDefaultHandling。如果图表管理器对某个事件码没有缺省的处理,调用这两个函数是不起作用的。
事件是如何发生的
为了处理事件,应用程序需要一种机制来获取正在队列中等待的事件。Filter图表管理器提供了两种方法。
1、窗口通知,图表管理器发送开发者自己定义的窗口消息
2、事件信号 如果队列中有dshow事件,就用事件信号通知应用程序,如果队列为空就重新设置事件信号。
下面的代码演示了如何利用消息通知
#define WM_GRAPHNOTIFY WM_APP + 1 // Private message.
pEvent->SetNotifyWindow((OAHWND)g_hwnd, WM_GRAPHNOTIFY, 0);
然后在窗口消息处理过程中处理该消息如下:
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));
}
由于事件通知和窗口的消息循环都是异步的,因此,当你的应用程序处理消息的时候,队列中或许有N个事件等待处理。因此,在你调用GetEvent的时候,一定要循环调用,直到返回一个错误码,这表明队列是空的。
当你释放IMediaEventEx 指针时,你可以调用SetNotifyWindow来取消事件通知,记住此时要给这个函数传递一个NULL指针。在你的事件处理程序中,在调用GetEvent之前一定要检查IMediaEventEx指针是否为空,这样就可以避免错误。
下面看看采取事件信号的通知方式。
在Filter图表管理器里有一个手动设置的Event内核对象,用来反映事件队列的状态。如果队列中有等待处理的事件,event就处于通知状态,如果队列是空的,IMediaEvent::GetEvent函数调用就会重置该event对象。
应用程序可以调用IMediaEvent::GetEventHandle获得event内核对象的句柄,然后就可以调用WaitForMultipleObjects来等待事件的发生,如果event被通知了,就可以调用IMediaEvent::GetEvent来获得dshow的事件。
下面的代码演示了如何利用event内核对象来获取EC_COMPLETE事件:
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(!bDone)
{
if (WAIT_OBJECT_0 == WaitForSingleObject(hEvent, 100))
{
while (hr = pEvent->GetEvent(&evCode, ¶m1, ¶m2, 0), SUCCEEDED(hr))
{
printf("Event code: %#04x/n Params: %d, %d/n", evCode, param1, param2);
pEvent->FreeEventParams(evCode, param1, param2);
switch (evCode)
{
case EC_COMPLETE: // Fall through.
case EC_USERABORT: // Fall through.
case EC_ERRORABORT:
CleanUp();
PostQuitMessage(0);
return;
}
}
}
事件通知码(Event Notification Codes)
常用的事件通知码如下:
Event notification code Description
1 EC_ACTIVATE
A video window is being activated or deactivated.
2EC_BUFFERING_DATA
The graph is buffering data, or has stopped buffering data.
3EC_BUILT
Send by the Video Control when a graph has been built. Not forwarded to applications.
4EC_CLOCK_CHANGED
The reference clock has changed.
5EC_CLOCK_UNSET
The clock provider was disconnected.
6EC_CODECAPI_EVENT
Sent by an encoder to signal an encoding event.
7EC_COMPLETE
All data from a particular stream has been rendered.
8EC_DEVICE_LOST
A Plug and Play device was removed or has become available again.
9EC_DISPLAY_CHANGED
The display mode has changed.
10EC_END_OF_SEGMENT
The end of a segment has been reached.
11EC_ERROR_STILLPLAYING
An asynchronous command to run the graph has failed.
12EC_ERRORABORT
An operation was aborted because of an error.
13 EC_EXTDEVICE_MODE_CHANGE
Not supported.
14EC_FULLSCREEN_LOST
The video renderer is switching out of full-screen mode.
15EC_GRAPH_CHANGED
The filter graph has changed.
16EC_LENGTH_CHANGED
The length of a source has changed.
17EC_NEED_RESTART
A filter is requesting that the graph be restarted.
18EC_NOTIFY_WINDOW
Notifies a filter of the video renderer's window.
19EC_OLE_EVENT
A filter is passing a text string to the application.
20EC_OPENING_FILE
The graph is opening a file, or has finished opening a file.
21EC_PALETTE_CHANGED
The video palette has changed.
22EC_PAUSED
A pause request has completed.
23EC_QUALITY_CHANGE
The graph is dropping samples, for quality control.
24EC_REPAINT
A video renderer requires a repaint.
25EC_SEGMENT_STARTED
A new segment has started.
26EC_SHUTTING_DOWN
The filter graph is shutting down, prior to being destroyed.
27EC_SNDDEV_IN_ERROR
An audio device error has occurred on an input pin.
28EC_SNDDEV_OUT_ERROR
An audio device error has occurred on an output pin.
29EC_STARVATION
A filter is not receiving enough data.
30EC_STATE_CHANGE
The filter graph has changed state.
31EC_STEP_COMPLETE
A filter performing frame stepping has stepped the specified number of frames.
32EC_STREAM_CONTROL_STARTED
A stream-control start command has taken effect.
33EC_STREAM_CONTROL_STOPPED
A stream-control start command has taken effect.
34EC_STREAM_ERROR_STILLPLAYING
An error has occurred in a stream. The stream is still playing.
35EC_STREAM_ERROR_STOPPED
A stream has stopped because of an error.
36EC_TIMECODE_AVAILABLE
Not supported.
37EC_UNBUILT Send by the Video Control when a graph has been torn down. Not forwarded to applications.
38EC_USERABORT
The user has terminated playback.
39EC_VIDEO_SIZE_CHANGED
The native video size has changed.
40EC_VMR_RENDERDEVICE_SET
Sent when the VMR has selected its rendering mechanism.
41EC_VMR_SURFACE_FLIPPED
Sent when the VMR-7's allocator presenter has called the DirectDraw Flip method on the surface being presented.
42EC_VMR_RECONNECTION_FAILED
Sent by the VMR-7 and the VMR-9 when it was unable to accept a dynamic format change request from the upstream decoder.
43EC_WINDOW_DESTROYED
The video renderer was destroyed or removed from the graph.
44EC_WMT_EVENT
Sent by the Windows Media Format SDK when an application uses the ASF Reader filter to play ASF files protected by digital rights management (DRM).
45EC_WMT_INDEX_EVENT
Sent by the Windows Media Format SDK when an application uses the ASF Writer to index Windows Media Video files.
如何处理事件
Filter图表管理器暴露了三个接口用来处理事件通知
IMediaEventSink Filter用这个接口来post事件。
IMediaEvent 应用程序利用这个接口来从队列中查询消息
IMediaEventEx 是imediaevent的扩展。
Filter都是通过调用图表管理器的 IMediaEventSink::Notify方法来通知图表管理器某种事件发生。事件通知包括一个事件code,这个code不仅仅代表了事件的类型,还包含两个DWORD类型的参数用来传递一些其他的信息。
关于事件code的内容,在下面的一个专题中列出,这里暂略,使用时可以参考帮助。
应用程序通过调用图表管理器的IMediaEvent::GetEvent方法来从事件队列中获取事件。如果有事件发生,该函数就返回一个事件码和两个参数,如果没有事件,则一直阻塞直到有事件发生和超过某个时间。调用GetEvent函数后,应用程序必须调用IMediaEvent::FreeEventParams来释放事件码所带参数的资源。例如,某个参数可能是由filter graph分配的内存。
下面的代码演示了如何从事件队列中提取事件
long evCode, param1, param2;
HRESULT hr;
while (hr = pEvent->GetEvent(&evCode, ¶m1, ¶m2, 0), SUCCEEDED(hr))
{
switch(evCode)
{
// Call application-defined functions for each
// type of event that you want to handle.
}
hr = pEvent->FreeEventParams(evCode, param1, param2);
}
为了重载Filter图表管理器对事件的缺省处理,你可以使用某个事件码做参数调用IMediaEvent::CancelDefaultHandling ,这样就可以屏蔽图表管理器对某个事件码的处理了。如果要恢复图表管理器对该事件码的缺省处理,可以调用 IMediaEvent::RestoreDefaultHandling。如果图表管理器对某个事件码没有缺省的处理,调用这两个函数是不起作用的。
事件是如何发生的
为了处理事件,应用程序需要一种机制来获取正在队列中等待的事件。Filter图表管理器提供了两种方法。
1、窗口通知,图表管理器发送开发者自己定义的窗口消息
2、事件信号 如果队列中有dshow事件,就用事件信号通知应用程序,如果队列为空就重新设置事件信号。
下面的代码演示了如何利用消息通知
#define WM_GRAPHNOTIFY WM_APP + 1 // Private message.
pEvent->SetNotifyWindow((OAHWND)g_hwnd, WM_GRAPHNOTIFY, 0);
然后在窗口消息处理过程中处理该消息如下:
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));
}
由于事件通知和窗口的消息循环都是异步的,因此,当你的应用程序处理消息的时候,队列中或许有N个事件等待处理。因此,在你调用GetEvent的时候,一定要循环调用,直到返回一个错误码,这表明队列是空的。
当你释放IMediaEventEx 指针时,你可以调用SetNotifyWindow来取消事件通知,记住此时要给这个函数传递一个NULL指针。在你的事件处理程序中,在调用GetEvent之前一定要检查IMediaEventEx指针是否为空,这样就可以避免错误。
下面看看采取事件信号的通知方式。
在Filter图表管理器里有一个手动设置的Event内核对象,用来反映事件队列的状态。如果队列中有等待处理的事件,event就处于通知状态,如果队列是空的,IMediaEvent::GetEvent函数调用就会重置该event对象。
应用程序可以调用IMediaEvent::GetEventHandle获得event内核对象的句柄,然后就可以调用WaitForMultipleObjects来等待事件的发生,如果event被通知了,就可以调用IMediaEvent::GetEvent来获得dshow的事件。
下面的代码演示了如何利用event内核对象来获取EC_COMPLETE事件:
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(!bDone)
{
if (WAIT_OBJECT_0 == WaitForSingleObject(hEvent, 100))
{
while (hr = pEvent->GetEvent(&evCode, ¶m1, ¶m2, 0), SUCCEEDED(hr))
{
printf("Event code: %#04x/n Params: %d, %d/n", evCode, param1, param2);
pEvent->FreeEventParams(evCode, param1, param2);
switch (evCode)
{
case EC_COMPLETE: // Fall through.
case EC_USERABORT: // Fall through.
case EC_ERRORABORT:
CleanUp();
PostQuitMessage(0);
return;
}
}
}
事件通知码(Event Notification Codes)
常用的事件通知码如下:
Event notification code Description
1 EC_ACTIVATE
A video window is being activated or deactivated.
2EC_BUFFERING_DATA
The graph is buffering data, or has stopped buffering data.
3EC_BUILT
Send by the Video Control when a graph has been built. Not forwarded to applications.
4EC_CLOCK_CHANGED
The reference clock has changed.
5EC_CLOCK_UNSET
The clock provider was disconnected.
6EC_CODECAPI_EVENT
Sent by an encoder to signal an encoding event.
7EC_COMPLETE
All data from a particular stream has been rendered.
8EC_DEVICE_LOST
A Plug and Play device was removed or has become available again.
9EC_DISPLAY_CHANGED
The display mode has changed.
10EC_END_OF_SEGMENT
The end of a segment has been reached.
11EC_ERROR_STILLPLAYING
An asynchronous command to run the graph has failed.
12EC_ERRORABORT
An operation was aborted because of an error.
13 EC_EXTDEVICE_MODE_CHANGE
Not supported.
14EC_FULLSCREEN_LOST
The video renderer is switching out of full-screen mode.
15EC_GRAPH_CHANGED
The filter graph has changed.
16EC_LENGTH_CHANGED
The length of a source has changed.
17EC_NEED_RESTART
A filter is requesting that the graph be restarted.
18EC_NOTIFY_WINDOW
Notifies a filter of the video renderer's window.
19EC_OLE_EVENT
A filter is passing a text string to the application.
20EC_OPENING_FILE
The graph is opening a file, or has finished opening a file.
21EC_PALETTE_CHANGED
The video palette has changed.
22EC_PAUSED
A pause request has completed.
23EC_QUALITY_CHANGE
The graph is dropping samples, for quality control.
24EC_REPAINT
A video renderer requires a repaint.
25EC_SEGMENT_STARTED
A new segment has started.
26EC_SHUTTING_DOWN
The filter graph is shutting down, prior to being destroyed.
27EC_SNDDEV_IN_ERROR
An audio device error has occurred on an input pin.
28EC_SNDDEV_OUT_ERROR
An audio device error has occurred on an output pin.
29EC_STARVATION
A filter is not receiving enough data.
30EC_STATE_CHANGE
The filter graph has changed state.
31EC_STEP_COMPLETE
A filter performing frame stepping has stepped the specified number of frames.
32EC_STREAM_CONTROL_STARTED
A stream-control start command has taken effect.
33EC_STREAM_CONTROL_STOPPED
A stream-control start command has taken effect.
34EC_STREAM_ERROR_STILLPLAYING
An error has occurred in a stream. The stream is still playing.
35EC_STREAM_ERROR_STOPPED
A stream has stopped because of an error.
36EC_TIMECODE_AVAILABLE
Not supported.
37EC_UNBUILT Send by the Video Control when a graph has been torn down. Not forwarded to applications.
38EC_USERABORT
The user has terminated playback.
39EC_VIDEO_SIZE_CHANGED
The native video size has changed.
40EC_VMR_RENDERDEVICE_SET
Sent when the VMR has selected its rendering mechanism.
41EC_VMR_SURFACE_FLIPPED
Sent when the VMR-7's allocator presenter has called the DirectDraw Flip method on the surface being presented.
42EC_VMR_RECONNECTION_FAILED
Sent by the VMR-7 and the VMR-9 when it was unable to accept a dynamic format change request from the upstream decoder.
43EC_WINDOW_DESTROYED
The video renderer was destroyed or removed from the graph.
44EC_WMT_EVENT
Sent by the Windows Media Format SDK when an application uses the ASF Reader filter to play ASF files protected by digital rights management (DRM).
45EC_WMT_INDEX_EVENT
Sent by the Windows Media Format SDK when an application uses the ASF Writer to index Windows Media Video files.
- DirectShow开发快速入门之三事件通知机制
- DirectShow开发快速入门之三 -- 事件通知机制
- DirectShow开发快速入门之事件通知机制
- DirectShow开发快速入门之事件通知机制
- Direct Show开发 快速入门之事件通知机制
- DirectShow开发快速入门之三
- DirectShow之事件通知机制(转)
- DirectShow开发快速入门之慨述(三)
- DirectShow中的事件通知机制
- DirectShow中的事件通知机制
- DirectShow中的事件通知机制
- DirectShow中的事件通知机制
- DirectShow开发快速入门之慨述
- DirectShow开发快速入门之慨述
- DirectShow开发快速入门之慨述
- DirectShow开发快速入门之慨述
- DirectShow开发快速入门之慨述
- DirectShow开发快速入门之慨述
- hehe
- DirectShow开发快速入门之一 -- 慨述
- 大学城寒假生存手册
- DirectShow开发快速入门之二 -- 数据流的流动
- “80后”程序员薪水为何这么低?
- DirectShow开发快速入门之三 -- 事件通知机制
- DirectShow系统初级指南
- 以前很喜欢的一首诗
- 使用DirectShow驱动摄像头
- DirectShow流媒体信息获取及图象转换
- 如何取消DELL640M“嘟”的报警声
- 梦断代码
- 职场指南:五招助你快升职
- 世界犬智商排名