概述

过滤器通过发布事件通知来通知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. 美国中学生被学校监控,实时位置、和谁接触一览无余
  2. 计算机视觉、图像分类、目标检测、人脸比对、人脸识别、语义分割、实例分割、图像搜索
  3. 清华大佬教你一招最便捷搭建 Zookeeper 的方法!
  4. 一个关于CentOS下apache配置修改生效的问题
  5. python正规教育机构-长沙python培训机构哪家好
  6. 编程python爬取网页数据教程_实例讲解Python爬取网页数据
  7. Magento后台表单字段添加备注
  8. linux 编译opencv 慢,opencv4.0 cuda10 编译速度太慢
  9. IOS-RunTime(刨根问底)
  10. c语言死循环中输入字符,如下代码,如果输入字符,为什么会造成死循环?
  11. Android开发学习——画横线竖线
  12. android debug 签名,Android Studio中debug模式下使用release签名
  13. 【大数据部落】出租车数据分析:用数据告诉你出租车资源配置是否合理
  14. 基于Flink CDC实现实时数据采集(一)-接口设计
  15. maven常用命令大全(附详细解释)
  16. 爬虫爬取视频指定秒的画面
  17. AtCoder Grand Contest 007 题解
  18. 攻防世界-misc高手进阶篇-2017_Dating_in_Singapore
  19. 【Linux】Linux的进程调度
  20. Wi-Fi 6 BSS着色和空间重用白皮书

热门文章

  1. 群聊系统项目(基于TCP、UDP实现)
  2. windows s2019设置JAVA_HOME环境变量
  3. 黑帽python第二版(Black Hat Python 2nd Edition)读书笔记 之 第八章 Windows常见特洛伊木马任务(4)沙箱检测
  4. 【LG手机】【刷机救砖教程】【F240】刷了recovery不慎手机变砖
  5. 百度竞价如何优化创意
  6. 可用于企业的 7 个开源 Web 服务器
  7. <<Java>>注释的三种方式
  8. 在linux中其他组没有权限怎么写,Linux 权限 用户 组 命令
  9. @html.textbox的使用方法,ASP.NET中 TextBox 文本输入框控件的使用方法
  10. Mybatis拦截器使用介绍