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

本文的目的是给出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"

 

"

posted @ 2012-09-06 09:59  c++ player  阅读(1037)  评论(0编辑  收藏  举报