概述

过滤器通过发布事件通知来通知Filter Graph Manager关于事件。 该事件可能是某种预期的结果,例如流结束,或者它可能表示错误,例如未能呈现流。 过滤器图形管理器本身处理一些过滤器事件,并使其他应用程序处理。 如果筛选器图形管理器不处理筛选器事件,它会将事件通知放入队列中。 过滤器图也可以为应用程序排队自己的事件通知。

应用程序从队列中检索事件,并根据事件的类型对它们做出响应。 因此,DirectShow中的事件通知与Microsoft Windows消息队列方案类似。 应用程序还可以取消给定事件类型的Filter Graph Manager的默认行为。 Filter Graph Manager然后将这些事件直接放入队列中供应用程序处理。

这种机制的作用如下:

·Filter Graph Manager与应用程序进行通信。

·筛选器与应用程序和Filter Graph Manager进行通信。

·确定其参与处理事件的程度的申请。

检索事件

Filter Graph Manager公开了三个支持事件通知的接口:

·IMediaEventSink包含过滤器发布事件的方法。

·IMediaEvent包含应用程序检索事件的方法。

·IMediaEventEx继承并扩展IMediaEvent接口。

通过在Filter Graph Manager上调用IMediaEventSink :: Notify方法过滤事件通知。事件通知由定义事件类型的事件代码和提供附加信息的两个参数组成。根据事件代码,参数可能包含指针,返回码,参考时间或其他信息。

要从队列中检索事件,应用程序会在Filter Graph Manager上调用IMediaEvent :: GetEvent方法。此方法会阻塞,直到有事件返回或者经过指定的时间。假设有一个排队事件,该方法返回事件代码和两个事件参数。调用GetEvent后,应用程序应始终调用IMediaEvent :: FreeEventParams方法来释放与事件参数关联的所有资源。例如,参数可能是由过滤器图形分配的BSTR值。

以下代码示例提供了如何从队列中检索事件的大纲:

long evCode;
LONG_PTR 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);
}

要覆盖筛选器图形管理器对事件的默认处理,请使用事件代码作为参数调用IMediaEvent :: CancelDefaultHandling方法。 您可以通过调用IMediaEvent :: RestoreDefaultHandling方法来恢复默认处理。 如果过滤器图形不对指定的事件代码执行默认处理,则调用这些方法不起作用。

Learning When an Event Occurs

为了处理DirectShow事件,应用程序需要找出事件在队列中等待的时间。 Filter Graph Manager提供了两种方式来执行此操作:

·Window notification:每当出现新事件时,Filter Graph Manager都会将用户定义的Windows消息发送到应用程序窗口。

·Event signaling:如果队列中存在DirectShow事件,则Filter Graph Manager将通知Windows事件,如果队列为空,则重置事件。

Window Notification

要设置窗口通知,请调用IMediaEventEx :: SetNotifyWindow方法并指定一条私人消息。 应用程序可以使用WM_APP到0xBFFF范围内的消息号作为私人消息。 只要Filter Graph Manager在队列中放置新的事件通知,它就会将此消息发布到指定的窗口。 应用程序响应来自窗口消息循环内的消息。

以下代码示例显示如何设置通知窗口。

#define WM_GRAPHNOTIFY WM_APP + 1   // Private message.
pEvent->SetNotifyWindow((OAHWND)g_hwnd, WM_GRAPHNOTIFY, 0);

该消息是普通的Windows消息,与DirectShow事件通知队列分开发布。 这种方法的优点是大多数应用程序已经实现了一个消息循环。因此,您可以合并DirectShow事件处理,而无需额外的工作。

以下代码示例显示了如何响应通知消息的大纲

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));
}

由于事件通知和消息循环都是异步的,因此在应用程序响应消息时,队列可能包含多个事件。 另外,如果事件无效,有时可以从队列中清除事件。 因此,在您的事件处理代码中,调用IAMMediaEvent :: GetEvent,直到它返回一个失败代码,指示队列为空。

在释放IMediaEventEx指针之前,通过用NULL指针调用SetNotifyWindow来取消事件通知。 在你的事件处理代码中,在调用GetEvent之前检查你的IMediaEventEx指针是否有效。 这些步骤可以防止应用程序在释放IMediaEventEx指针后收到事件通知的可能错误。

Event Signaling

过滤器图形管理器保留反映事件队列状态的手动重置事件。 如果队列包含待处理事件通知,则Filter Graph Manager将发出手动重置事件的信号。 如果队列为空,则调用IMediaEvent :: GetEvent方法将重置该事件。 应用程序可以使用此事件来确定队列的状态。

调用IMediaEvent :: GetEventHandle方法来获取手动重置事件的句柄。 通过调用诸如WaitForMultipleObjects之类的函数来等待事件发出信号。 一旦事件发出信号,请致电IMediaEvent :: GetEvent获取DirectShow事件。以下代码示例说明了这种方法。 它获取事件句柄,然后以100毫秒的间隔等待事件发出信号。 如果事件发出信号,它会调用GetEvent并将事件代码和事件参数打印到控制台窗口。 当EC_COMPLETE事件发生时,循环终止,表明播放已完成。

以下代码示例说明了这种方法。 它获取事件句柄,然后以100毫秒的间隔等待事件发出信号。 如果事件发出信号,它会调用GetEvent并将事件代码和事件参数打印到控制台窗口。 当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 (S_OK == pEvent->GetEvent(&evCode, ¶m1, ¶m2, 0)) {printf("Event code: %#04x\n Params: %d, %d\n", evCode, param1, param2);pEvent->FreeEventParams(evCode, param1, param2);bDone = (EC_COMPLETE == evCode);}}
} 

由于过滤器图形会在适当时自动设置或重置事件,因此您的应用程序不应该这样做。 另外,当您释放过滤器图形时,过滤器图形会关闭事件句柄,因此请勿在该点之后使用事件句柄。

参考:

https://www.yuque.com/docs/share/1999a291-72fc-43b0-92a5-ff615c88141f

DirectShow之事件通知相关推荐

  1. WMI技术介绍和应用——事件通知

    在<WMI技术介绍和应用--WMI概述>中,我们使用了下图介绍WMI构架(转载请指明出于breaksoftware的csdn博客) 我们之前介绍的使用WMI查询系统.硬件等信息的功能,是通 ...

  2. python 事件通知模式_请问在 Python 的事件系统中,如何可以通过事件通知立刻终结一个正在运行的子线程?...

    大家好,最近在完善手头上一个基于事件系统的 GUI . 现在遇到一个问题,就是当我在执行一个按钮点击事件的时候,实际会开一个子线程进行业务逻辑的处理,这个处理过程可能会比较长,并且中间可能会出现一些不 ...

  3. spring事件通知机制详解

    优势 解耦 对同一种事件有多种处理方式 不干扰主线(main line) 起源 要讲spring的事件通知机制,就要先了解一下spring中的这些接口和抽象类: ApplicationEventPub ...

  4. 事件通知方式实现的重叠I/O模型

    // /// 事件通知方式实现的重叠I/O模型(异步IO模型) /// 这个模型的基本的设计实现是允许应用程序使用重叠的数据结构一次投递一个或者多个异步I/O /// 请求 /// 这个模型与上述其他 ...

  5. C语言 串口通知消息,编程模式·观察者模式、事件通知、消息队列三者区别

    观察者模式.事件通知.消息队列三者有类似,都有回调函数注册,通知调用的设计,容易混淆. 简述和区别 观察者模式:被观察对象状态改变,所有观察它的对象得到通知.也称订阅模式,英文Observer. 被观 ...

  6. java 简单事件的使用,如何正确的使用Java事件通知(1)

    如何正确的使用Java事件通知(1) 通过实现观察者模式来提供 Java 事件通知(Java event notification)似乎不是件什么难事儿,但这过程中也很容易就掉进一些陷阱.本文介绍了我 ...

  7. java 事件通知_正确获取Java事件通知

    java 事件通知 实现观察者模式以提供Java事件通知似乎是一件容易的事. 但是,容易陷入一些陷阱. 这是我在各种场合不慎造成的常见错误的解释-- Java事件通知 让我们从一个简单的bean St ...

  8. 正确获取Java事件通知

    实现观察者模式以提供Java事件通知似乎是一件容易的事. 但是,容易陷入一些陷阱. 这是我在各种场合不慎造成的常见错误的解释-- Java事件通知 让我们从一个简单的bean StateHolder开 ...

  9. ECS事件通知之创建失败事件

    ECS提供了批量实例创建接口,可以一次调用创建最多100台实例.批量创建接口可以完成批量实例的创建.启动.IP分配等流程,可以快速完成实例资源的扩容. 在实例的创建过程中(实际后台异步创建),库存和V ...

最新文章

  1. Windows开启WMI时一些总结
  2. mysql 事务值被改变_面试被问MySQL 事务的实现原理,怎么破?
  3. 现代控制理论第八版第二章读书笔记
  4. 北京规定6类高级人才来京最高奖励30万元
  5. 第三次学JAVA再学不好就吃翔(part97)--抛出异常
  6. koa --- 扩展hbs方法
  7. 解决“A problem has been encountered while loading the setup components. Canceling setup.”的问题...
  8. c 打印 callback 函数名_Go 中的函数
  9. HTML5 API详解(15):History 不刷新也可以实现网页跳转
  10. 浅谈Rem 及其转换原理
  11. [论文摘录] Web Service QoS的几个研究方向
  12. 静态的顺序表(C语言实现)
  13. 三次握手与accept()函数
  14. DEFINE_MUTEX
  15. 外汇买入价、外汇卖出价、现钞买入价有什么区别?
  16. 二分法(yxc讲解+模板整理)
  17. 情态动词学习笔记(1) 表推测
  18. Java面向对象:Account类
  19. Java编程思想读书笔记-7
  20. ubc本科计算机雅思要求,英属哥伦比亚大学雅思要求

热门文章

  1. position定位的基准问题
  2. mysql创建视图语法_MySQL教程91-MySQL创建视图
  3. 百度关键词ad竞价的优劣势分析,信息流优化师必看
  4. 使用STM32 ST-LINK Utility下载程序教程
  5. 联想拯救者相关驱动问题修复及升级
  6. matplotlib 修改字体,解决中文显示乱码的问题
  7. php链接odbc,PHP使用ODBC连接数据库的方法
  8. SQL Sever触发器的基本语法与作用
  9. 搭建dedecms(织梦cms)框架
  10. JEB反编译器crack版功能和选项