正文

DirectShow应用程序快速入门2006-04-20 15:42:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/ddtme/12778.html

分享到:

 

摘要:该文介绍如何编写DirectShow应用程序,属于入门级文章。载自博客blog.csdn.net/suntaoznz

 

环境设置... 1

DirectShow编程简介... 1

播放文件例程... 3

 

 

一环境设置

该节介绍如何建立DirectShow应用程序。你可以建立一个控制台程序,或者Visual Studio环境下的其它Visual C++的项目。

头文件

所有DirectShow 程序都使用下表中的头文件。

 

头文件

    

dshow.h

所有DirectShow 程序。

 

有些DirectShow接口会要求其他头文件,你可以去查看这些接口的参考手册。

 

库文件

DirectShow程序要使用的库文件如下:

 

库文件

           

Strmiids.lib

提供类标识(CLSIDs)和接口表示(IIDs)。所有的DirectShow程序都要求使用该库文件。

Quartz.lib

提供AMGetErrorText函数,如果你不调用这个函数,就可以不加载该库文件。

 

可以把DirectX SDK Include Lib目录放在Visual Studio的搜索路径的第一位。以确保你可以使用最新的版本!

 

 

DirectShow编程简介

该节对DirectShow编程的基本术语和概念进行介绍,通过对该节的阅读,你可以写你的一个DirectShow应用程序。

过滤器(Filters)和过滤器图表(Filter Graphs

过滤器(Filters)就是一个软件组件,它执行一些针对多媒体流的操作。比如:

·         读入文件

·         从视频捕获设备得到视频

·         对多种流格式解码,如MPEG-1

·         传送数据到显卡和声卡

 

过滤器可以接收输入并提供输出,比如,一个MPEG-1视频解码过滤器,它接收MPEG编码的数据流,通过处理后输出非压缩的视频图像帧。

DirectShow, 应用程序执行的一些工作是在一串过滤器链接中完成,可能某个过滤器的输出到了下一步就是另一个过滤器的输入。这一组连接,我们就称为过滤器图表

例如下图显示了一个播放AVI文件的过滤器图表。

  

File Source 过滤器从硬盘上读取AVI文件。AVI Splitter 过滤器把文件解析为两个数据流(压缩的视频流和音频流)AVI Decompressor过滤器对视频流解码,Video Rendere把视频数据显示出来(通过DirectDraw GDI)。Default DirectSound Device过滤器使用DirectSound播发音频数据

应用程序不需要对数据流动进行管理,这些过滤器被级别更高的组件控制,过滤器图表管理器Filter Graph Manager)管理这些过滤器。这样,你就可以使用更高级别的API来控制(比如Run” , ”Stop”),如果你要控制流的操作,你也可以通过直接使用过滤器的COM接口实现。过滤器图表管理器通过事件来通知应用程序。

过滤器图表管理器的另一个用途是:它通过把过滤器连接在一起,向应用程序提供了建立过滤器图表的方法。

编写DirectShow 程序

在大部分的情况下,DirectShow应用程序必须执行下面3个步骤:

1.       应用程序建立一个Filter Graph Manager的实例。

2.       应用程序使用Filter Graph Manager 去建立一个filter graph. Filter graph中的过滤器依赖与应用程序的需求。

3.       应用程序使用Filter Graph Manager 去控制filter graph 并通过过滤器去对数据解析分流。在整个处理过程中,应用程序都将响应Filter Graph Manager的事件。

当处理完成后,应用程序将释放掉Filter Graph Manager和所有的过滤器。

DirectShow 是基于COM的。Filter Graph Manager 和过滤器都是COM对象。你应该对COM编程有全面的了解。

三播放文件例程

这里提供一个控制台应用程序去播放一个音、视频文件。这个程序只有几行长。

在前面介绍了一个基于DirectShow的应用程序,必须要进行如下几个基本步骤:

1.       建立一个Filter Graph Manager的实例.

2.       使用Filter Graph Manager 建立一个filter graph.

3.       运行这个graph

调用CoInitialize 去初始化一个这个COM 库。

HRESULT hr = CoInitialize(NULL);

if (FAILED(hr))

{

    // 在这里加入错误处理

}

这里,我们跳过了对返回值的检查,当你调用了任何方法的时候都应该对返回值进行检查。下面调用CoCreateInstance创建Filter Graph Manager

IGraphBuilder *pGraph;

HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL,

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

IDCLSID_FilterGraph,由于Filter Graph Manager是动态链接库提供(dll),所以使用CLSCTX_INPROC_SERVER

CoCreateInstance 将返回IgraphBuilder接口,在该例子中还需要两个接口:

l         IMediaControl 用于控制数据流。它提供停止和开始的操作方法。

l         IMediaEvent   可以获得Filter Graph Manager 事件。例如,可以获得播放完成事件。

这两个接口都由Filter Graph Manager提供,可以通过IgraphBuilder指针去获得它们:

IMediaControl *pControl;

IMediaEvent   *pEvent;

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

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

现在,你可以建立过滤器图表(Fileter Graph)。对于文件播放,这里只需要调用一个方法就可以了:

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

IGraphBuilder::RenderFile方法将建立一个过滤器图表,通过它来播放指定的文件。第一个参数指定要播放的文件名称,它是个宽字符字符串。第二个参数是系统保留,必须为NULL。如果指定文件不存在或文件格式未知,那么该方法调用将失败。

现在过滤器图表已经准备好了去播放文件,但是还必须调用IMediaControl::Run方法去播放。

hr = pControl->Run();

当过滤器图表开始运行,数据从通过过滤器播放出来。播放动作将在一个独立的线程中进行。调用IMediaEvent::WaitForCompletion 方法可以等待文件播放完成。

long evCode = 0;

pEvent->WaitForCompletion(INFINITE, &evCode);

这个方法将一直等待文件播放结束才返回。INFINITE就表示不能确定文件的播放时间长度。当应用程序完成播放后,应该释放掉接口指针和关闭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);

        }

    }

    pControl->Release();

    pEvent->Release();

    pGraph->Release();

    CoUninitialize();

}

 

阅读(9170) | 评论(2)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

loading...
您需要登录后才能评论,请 登录 或者 注册