SDN一开始介绍DirectShwo的时候就给出了一个列子“How To Play a File“,代码如下:

这是一个控制台程序,Render会创建一个自己的窗口来播放视频。如果在MFC的对话框中执行这段代码,就会出现两个窗口,一个是Render创建的播放窗口,一个是程序的主窗口。MSDN告诉我们,可以把Render创建的窗口设置为主窗口的子窗口。这样,播放窗口就会贴附在主窗口上。使用IVideoWindow接口实现,代码如下:

运行程序,执行RenderFile()函数,发现效果没变,还是两个窗口,怎么回事呢?单步调试跟踪发现,pWnd->put_Owner没有返回S_OK,而是返回E_NOINTERFACE,无效的接口指针,很奇怪,pWnd是一个有效的值,但是随后的几个函数执行都是返回E_NOINTERFACE。很明显,窗口设置不成功,没辙,只好世界各地寻找不成功的原因。
对比了DXSDK/Samples/C++/DirectShow/Editing/StillCap中的例子发现,pGraph->RenderFile()函数与pWnd->put_Owner()的执行顺序反了。于是把hr = pGraph->RenderFile(L”C://Example.avi”, NULL)放到hr = pGraph->QueryInterface(IID_IVideoWindow,(void**)&pWnd)之前执行,OK,达到了效果,所有执行都返回S_OK。

虽然找到了错误的地方,也达到了效果,不过,使用一项技术,总还是要弄明白原理。于是我把MSDN中相关的内容又好好的看了一遍,发现原来如此:

在这个例子中,看不到添加任何filter的影子,既没有Source Filter ,又没有Render Filter,仅仅一句RenderFile()。是的,RenderFile()干了所有的事情。
首先IGraphBuilder::RenderFile()调用IGraphBuilder::AddSourceFilter()向Graph中添加一个Source Filter。IGraphBuilder::AddSourceFilter()会根据文件扩展名或者是文件头等信息智能选取一个匹配文件的Source Filter。
然后IGraphBuilder::RenderFile()调用IGraphBuilder::Render()完成剩下的Graph的生成。IGraphBuilder::Render()会从Source Filter的output pin开始寻找每一个匹配此pin的Filter加入到链路中来,直到找到一个Render Filter为止。当整个链路完成,也就代表Graph生成,可以调用pControl->Run()运行Graph了。
虽然IVideoWindow是由Filter Graph Manager暴露,但是IVideoWindow设置属性却是对Render Filter。在没有执行RenderFile之前,Graph中没有连接RenderFile,因此IVideoWindow的设置无效。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注