您的位置:首页 > 其它

如何使用DirectShow播放一个文件

2014-05-07 23:05 453 查看
本文的目的是给出DirectShow编程的样式。这是一个简单的控制台应用程序,用来播放一个音频或视频文件。程序只有几行,但是它示范了DirectShow编程的某些能力。
  如<DirectShow应用程序编程介绍>所写,一个DirectShow应用程序运行的基本步骤为:
1、创建一个筛选器表管理器的实例

2、使用筛选器表管理器生成一个筛选器表

3、运行表,使数据在筛选器中流动。

  调用CoIntitialize来初始化COM库

HRESULT hr = CoInitialize(NULL);

if (FAILED(hr))

{

// 在这里添加错误处理代码(Omitted for clarity.)

}

  为了简单化,此例子忽略了返回值,但是您最好在方法调用中检查HRESULT的值。

  下面,调用CoCreateInstance来创建筛选器表管理器:

IGraphBuilder *pGraph;

HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL,

CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);

   如上所示,类标识(CLSID)为CLSID_FilterGraph。筛选器表管理器由一个进程内的DLL提供,所以执行上下文是 CLSCTX_INPROC_SERVER。DirectShow支持自由自由线程处理模式,因此您也可以使用COINIT_MULTITHREADED 标志调用CoInitializeEx。
  对CoCreateInstance的调用返回IGraphBuilder接口,它主要包含了生成筛选器表的方法。此例中用到的另两个接口为:

IMediaControl,作用是控制流。它包含了停止和启动表的方法
IMediaEvent,它包含的方法是从筛选器表管理器中得到事件。在此例中,此接口用来等待播放的结束。

  这两个接口都是出现在筛选器表管理器中。可以使用返回的IGraphBuilder指针来查询。

IMediaControl *pControl;

IMediaEvent *pEvent;

hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);

hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);

  现在您可以生成筛选器表了。要播放文件,可以调用下列方法:

hr = pGraph->RenderFile(L"C://Example.avi", NULL);

  IGraphBuilder::RenderFile方法生成一个筛选器表,用以播放指定的文件。第一个参数是文件名称,用一个宽字符(2字节)字符串表示。第二个参数是保留参数,必须为NULL。

  如果指定的文件不存在,或文件格式无法,此方法将失败。如果方法调用成功,筛选器还原器就做好播放的准备了。要运行表,调用IMediaControl::Run方法。

hr = pControl->Run();

  当筛选器运行时,数据从筛选器中移出,并以视频和音频的方式还原出来。播放会启动另一个线程。您可以调用IMediaEvent::WaitForCompletion方法。

long evCode = 0;

pEvent->WaitForCompletion(INFINITE, &evCode);

  当应用程序结束时,将释放接口指针并关闭COM库。

pControl->Release();

pEvent->Release();

pGraph->Release();

CoUninitialize();

代码范例

  这里列出了本文介绍的例子的完整代码:

#include <dshow.h>

void main(void)

{

IGraphBuilder *pGraph = NULL;

IMediaControl *pControl = NULL;

IMediaEvent *pEvent = NULL;
// 初始化COM库

HRESULT hr = CoInitialize(NULL);

if (FAILED(hr))

{

printf("ERROR - Could not initialize COM library");

return;

}
// 创建筛选器表管理器,并查询接口

hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,

IID_IGraphBuilder, (void **)&pGraph);

if (FAILED(hr))

{

printf("ERROR - Could not create the Filter Graph Manager.");

return;

}
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);

hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
// 创建表。重点:将字符串改为您系统上的文件名称

hr = pGraph->RenderFile(L"C://Example.avi", NULL);

if (SUCCEEDED(hr))

{

// 运行表

hr = pControl->Run();

if (SUCCEEDED(hr))

{

// 等待结束

long evCode;

pEvent->WaitForCompletion(INFINITE, &evCode);
// 注意:在实际应用程序中不要使用INFINITE

// 因为它对应用程序的阻塞很不确定

}

}

pControl->Release();

pEvent->Release();

pGraph->Release();

CoUninitialize();

}
  此方法将阻塞,直到文件播放完毕,或超出了指定的时间。INFINITE值是指应用程序将阻塞到文件播放完。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: