电信主站 网通分站
购买流程 付款方式 常见问题 在线提问 续租服务 购物车
用户名: 密 码: 忘记密码?
首 页
域名注册
虚拟主机
双线主机
服务器租用
VPS主机
企业邮局
代理专区
客服中心
虚拟主机行业资讯 虚拟主机评测对比 互联网最新动态 技术学院 站长资讯 在线教程 网站运营
搜索优化 服务器 网络编程 图形图象 站长之家 网页制作 操作系统
冲浪宝典 软件教学 视频通信 办公软件 邮件系统 网络安全 认证考试
您当前位置:西部数码->资讯中心-> 在线教程-> .NET
DirectShow SDK笔记【关于DirectShow(3)】-.NET教程,评论及其它
作者:网友供稿 点击:12
  西部数码-全国虚拟主机10强!20余项虚拟主机管理功能,全国领先!第6代双线路虚拟主机,南北访问畅通无阻!虚拟主机可在线rar解压,自动数据恢复设置虚拟目录等.虚拟主机免费赠送访问统计,企业邮局.Cn域名注册10元/年,自助建站480元起,免费试用7天,满意再付款!P4主机租用799元/月.月付免压金!
文章页数:[1] 
4.3 filter states
    filter有三种状态,停止,暂停,运行。暂停状态是为了在graphcue data, 使得运行命令可以立即响应。filter graph manager控制着所有状态的转换。当应用程序调用imediacontrolrun, pause, stop方法时, filter graph manager就调用所有filter的相应imediafilter方法。停止,运行状态的切换总是要经过暂停,因此,当应用程序对停止的graph 调用run命令时,filter图表管理器在run之前首先要暂停。对于大多数的filter来说,runningpaused状态是一样的。考虑如下的filter graph:
    source -> transform -> renderer
    假定source filter不是实时源。当source filter暂停,它创建一个线程生成新的数据并尽可能快的写入到media samples. 线程通过调用transform filter的输入pin上的imeminputpin receive方法把数据向下推。transform filter接收到在source filter的线程中的sample.它可能用一个工作线程把sample递送给renderer,但是通常是在同一个线程完成。此时renderer暂停,它等待接收sample. 在接收到一个sample后,它就阻塞线程并不定的保存数据。如果是视频renderer, sample作为张贴图像显示,如果必要就重画图像。
    现在,数据流完全准备好进行提交。如果graph保持暂停,在第一帧samplesample就堆积在graph, 直到每个filter都阻塞在receivegetbuffer. 但是不会有数据丢失。一旦source线程非阻塞,它简单从阻塞的点恢复。
    source filtertransform filter忽略从暂停到运行的变换,它们简单的尽可能快的继续处理数据。当render开始运行,它就开始提交sample. 首先提交的就是当它阻塞时保存的sample. 然后,每次都接收到新sample. 计算sample的提交时间。(细节可参考time and clocks in directshow),render会保存每个sample直到提交时间,到点后再提交sample. 当它等待提交时间时,线程也阻塞在receive方法,或者在工作线程用队列接收sample. renderer向上的所有filter都不会陷于时间安排。
    实时源(比如捕捉设备)与普通结构有些不同。在实时源中,不合适提前准备任何数据。应用程序可能暂停graph,在运行前等待比较长的时间。graph不应该提交过时sample. 因此,暂停时实时源不会产生数据,只有运行时才有。为了把事件通知给filter graph manager, source filterimediafilter方法getstate返回vfw_s_cant_cue。此返回值表示filter已经转换到暂停状态,即使renderer没有接收到任何数据。
    当一个filter停止时,它拒绝发送给它的任何samplessource filter关闭他们的stream线程,其他filter也关闭他们创建的工作线程,pindecommit他们的内存分配器。
 
    4.3.1   state transitions
    filter graph manager按照逆流的方向来切换filter的状态,从renderer filtersource filter,这种方式可以防止死锁和sample的丢失。最关键的状态切换是暂停和停止之间。
    ·从停止到暂停,当filter暂停时就准备好了从连接filter接收samplesource filter是最后一个暂停的。它创建streaming线程发送sample,因为下游的filter的状态都已经切换到暂停了,所以,所有的filter都可以接收sample。只有当graph所有的renderer都接收到samplefilter graph manager才算完成了状态的切换(除了前面讲的实时源例外)
    ·从暂停到停止。当filter停止时它要释放它拥有的所有的sample以使得上一级filter中的imemallocator::getbuffer调用脱离阻塞。如果filterreceive函数中等待资源,它也会停止等待,并从receive返回,以使调用filter解锁。因此,当filter graph manager停止连接的上一级filter时,filter就不会在getbufferreceive函数中阻塞,也就能响应停止命令。上级filter在得到停止命令前可以会递送一些额外sample。但是下级filter可能拒绝他们,因为他们已经停止。
    4.4 pull model
imeminputpin接口中,上级filter决定发送什么样数据,然后将数据推给下filter。但对某些filter,拉模式更适合。现在,下filter向上filter请求数据。数据依然是从上级到下级,从输出pin到输入pin,但是由下filter发动数据流动。这种类型连接采用的是iasyncreader接口。
   拉模式的典型应用是文件回放。例如在avi文件的回放graph中,async file source filter就执行通用文件读写操作,然后将数据以字节流的方式(不带格式信息)发送给下filteravi splitter读取avi头并把数据流分析为视频、音频流。avi splitter能比async file source filter更好的决定它需要什么类型的数据,因此它用imeminputpin代替iasyncreader接口。
    为了从输出pin请求数据,输入pin调用如下一种方法:
    ·iasyncreader::request
    ·iasyncreader::syncread
    ·iasyncreader::syncreadaligned
    第一个方法是异步的,支持多个重叠读写。其他是同步的。
    理论上,任何filter可以支持iasyncreader,但是实际上它被设计来连接source filterparser filterparser的功能与推模式中的source filter非常相同。当它暂停时,创建一个数据流线程从iasyncreader连接拉数据,并推向下一级。输出pin使用imeminputpingraph的余下部分使用标准的推模式。
 
5. event notification in directshow
 
    5.1 overview of event notification
    某个事件发生时,比如数据流结束,产生一个错误,提交流失败等,filter就给filter graph manager发送一个事件通知。filter graph manager自己处理部分事件,另一部分交给应用程序处理。如果filter graph manager没有处理事件,它就把事件通知放入到一个队列中。图表管理器也可以将自己的事件通知放进队列中。
    应用程序以事件队列获取事件并根据事件类型进行处理。directshow中的事件通知和windows的消息机制差不多。应用程序也可以取消filter graph manager特定事件的默认行为。filter graph manager就直接把事件放入队列,留给应用程序来处理。
 
    5.2 retrieving events
    filter graph manager暴露了三个接口处理事件通知:
    ·imediaeventsink  filter用这个接口来post事件。
    ·imediaevent       应用程序利用这个接口来从队列中查询消息。
    ·imediaeventex     imediaevent的扩展。
    filter通过imediaeventsink::notify方法向filter graph manager提交事件。事件通知包括一个事件code,这个code不仅仅代表了事件的类型,还包含两个dword类型的参数用来传递一些其他的信息。根据不同的事件code,附加信息可能是指针、返回码、参考时间或其他信息。获取事件code和参数的全部列表可参考event notification codes.
    应用程序通过调用imediaevent::getevent从事件队列中获取事件。如果有事件发生,该函数就返回一个事件码和两个参数,如果没有事件,则一直阻塞直到有事件发生和超过某个时间。调用getevent函数后,应用程序必须调用imediaevent::freeeventparams来释放事件码所关联的资源。例如,参数可能是filter graph分配的bstr内存。下面的代码演示了如何从事件队列中提取事件:
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->freeeventparams(evcode, param1, param2);
}
    为了重载filter graph manager对事件的缺省处理,可以用某个事件码做参数调用imediaeventcanceldefaulthandling方法。这样就可以屏蔽filter graph manager对某个事件码的处理了。如果要恢复图表管理器对该事件码的缺省处理,可以调用restoredefaulthandling方法。如果filter graph对某个事件没有缺省的处理,调用这两个函数是不起作用的。
 
    5.3 learning when an event occurs
    为了处理directshow事件,应用程序需要一种机制来知道什么时候队列中有等待的事件。filter graph manager提供了两种方法:
    ·窗口通知:filter graph manager发送开发者自己定义的窗口消息
    ·事件信号:如果队列中有directshow事件,就用事件信号通知应用程序,如果队列为空就重新设置事件信号。
    应用程序可以使用这两种技术。窗口通知通常更简单。
 
    5.3.1   window notification
    建立窗口通知可调用imediaeventex::setnotifywindow方法,并指定一个私有消息。应用程序可使用从wm_app0xbfff之间的消息值作为私有消息。只要filter graph manager把一个新事件放入到队列时,就向目标窗口发送消息。应用程序从消息队列响应消息。
下面的代码演示了如何利用消息通知:
#define wm_graphnotify wm_app+1    // private message.
pevent->setnotifywindow((oahwnd)g_hwnd, wm_graphnotify, 0);
    消息是一个普通的窗口消息,是从directshow的事件通知队列单独提交的。这种方法的好处多数程序已经实现了消息循环。因此,我们可以合并directshow的事件通知而不需要过多额外工作。下面的代码说明了如何响应消息通知的框架。完整的例子可参考responding to events.
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指针是否为空,这样就可以避免错误。因为有时在释放imediaeventex指针后可能会得到通知。
 
    5.3.2   event signaling
    filter graph manager里有一个手动设置的event内核对象,用来反映事件队列的状态。如果队列中有等待处理的事件,event就处于通知状态,如果队列是空的,imediaevent::getevent函数调用就会重置该event对象。应用程序可利用此事件来判断队列的状态。
    应用程序可以调用imediaevent::geteventhandle获得event内核对象的句柄,然后就可以调用waitformultipleobjects来等待事件的发生,如果event被通知了,就可以调用getevent来获得directshow的事件。下面的代码演示了事件信号。返回事件句柄,再等待1000毫秒。如果事件变为信号状态,调用getevent返回事件code和参数。获取到ec_complete事件code时表示回放结束中止循环:
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, &param1, &param2, 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;
             }
        }
    }
}

文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!
相关主题
文章页数:[1] 
Google
热门文章
·经典收藏之 - C++内存管理详解-.NET教程,C#语言
·Master Page 初探-.NET教程,评论及其它
·GDI+编程10个基本技巧-.NET教程,评论及其它
·VB.NET中让Textbox只能输入数字(二)-.NET教程,VB.Net语言
·stl应用小问题-.NET教程,评论及其它
·WIN32中颜色值(COLORREF)与.NET中颜色值(Color)的转换-ASP教程,系统相关
·打造自己的专业图像工具-Visual C++ 2005图像编程系列【三】-.NET教程,C#语言
·.Net中常见问题及解决方法归类-.NET教程,.NET Framework
·Lex和Yacc从入门到精通(3)--一个极其简单的lex和yacc程序-.NET教程,评论及其它
·VB下几个非常有用的函数-.NET教程,VB.Net语言

最新文章
·VC#初学入门:第一个Windows程序
·ASP.NET 2.0-选用DataSet或DataReader
·用.net 处理xmlHttp发送异步请求
·asp.net创建文件夹的IO类的问题
·asp.net 2.0 中加密web.config 文件中的配置节
·关于ASP.NET调用JavaScript的实现
·如何实现ASP.NET网站个性化
·Acegi安全系统的配置-.NET教程,评论及其它
·Spring安全系统:Acegi Security Acegi简介-.NET教程,评论及其它
·Biztalk 开发之 架构和实例的验证-.NET教程,评论及其它


 
 


版权申明:本站文章均来自网络,如有侵权,请联系我们,我们收到后立即删除,谢谢!

特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。
  打印  刷新  关闭
返回首页 |关于我们 | 联系我们 | 付款方式 | 创业联盟 | 虚拟主机 | 资讯中心 | 友情链接 | 网站地图

版权所有 西部数码(www.west263.com)
CopyRight (c) 2002~2006 west263.com all right reserved.
公司地址:四川成都市万和路90号天象大厦4楼 邮编:610031
电话总机:028-86262244 86263048 86263408 86263960 86264018 86267838
售前咨询:总机转201 202 203 204 206 208
售后服务:总机转211 212 213 214
财务咨询:总机转224 223 传真:028-86264041 财务QQ:点击发送消息给对方635483282
售前咨询QQ:点击发送消息给对方2182518 点击发送消息给对方241975952 点击发送消息给对方275026793 点击发送消息给对方408235859
售后服务QQ:点击发送消息给对方17708515 点击发送消息给对方307742704 点击发送消息给对方287976517 点击发送消息给对方363783715
《中华人民共和国增值电信业务经营许可证》编号:川B2-20030065号