您的位置:首页 > 其它

控制台使用directshow播放一个文件

2012-09-06 09:59 447 查看
本文的目的是给出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值是指应用程序将阻塞到文件播放完。

article from "http: //blog.csdn. net/peng6662001/article/details/2110772"

"
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: