2. 开始DirectShow旅程
    这个章节的内容主要是编写DirectShow应用所需的一些基本概念,可以把它当作一个高级介绍,理解这些内容只需具备一般的编程和有关多媒体的知识。
2.1. 设置DirectShow开发的编译环境
    这节内容描述了如何来编译DirectShow应用。你可以使用命令行形式来编译一个工程,也可以在Microsoft Visual Studio集成环境下(包含VC++)实现。
    头文件:
    所有的DirectShow应用都需要Dshow.h这个头文件,某些DirectShow接口需要附加的头文件,参考接口的说明视具体情况定。
    库文件:
    DirectShow使用以下库文件:
    Strmiids.lib 输出类标识(CLSID)和接口标识(IID),所有DirectShow应用均需此库。
    Quartz.lib   输出AMGetErrorText函数,如果不调用此函数,此库不是必需的。
    有了以上这些头文件和库文件,你已经可以编写DirectShow应用了,但是微软建议使用DirectShow基类库来编写filter,这样可以大大减少程序编写的工作量。要使用DirectShow基类库,需要先编译它,基类库位于SDK的Samples/Multimedia/DirectShow/BaseClasses文件夹下,包含两个版本的库:发布版(retail version)Strmbase.lib和调试版(debug version)Strmbasd.lib。具体参见"创建DirectShow Filter"一节。
2.2. DirectShow应用程序编程简介
    这节介绍DirectShow用到的一些基本术语和概念,看完这节后,你将能够编写你的第一个DirectShow应用程序。
    Filter和Filter Graph
    一个DirectShow应用程序是由一个个称为filter的软件构件组合而成的,filter执行一些多媒体流的操作,如:读文件、从视频采集设备中获得视频、将不同的格式的流解码如MPEG1、将数据送到图形卡或声卡中去。
    Filter接收输入并产生输出。举个例子,一个解码MPEG1视频流的filter,输入MPEG1格式的视频流,输出一系列未压缩的视频帧。
    在DirectShow中,应用程序要实现功能就必须将这些filter链接在一起,因而一个filter的输出就变成了另一个filter的输入。这一系列串在一起的filter称为filter graph。例如,下图就显示了一个播放avi文件的filter graph:

    File Source(Async) filter从硬盘中读取avi文件;AVI Splitter filter分析文件并将其分解成两个流:一个压缩的视频流和一个音频流;AVI Decompressor filter将视频帧解码,Video Renderer filter将解码后的视频帧通过DirectDraw或GDI显示出来;Default DirectSound Device filter使用DirectSound播放音频流。
    应用程序没有必要对这些数据流进行管理,而是通过一个叫Filter Graph Manager这个上层组件来控制这些filter。应用程序调用上层API如"Run"(通过graph移动数据)或"Stop"(停止移动数据)。如果你需要对数据流作更多的操作,你可以通过COM接口直接进入filter。Filter Graph Manager同样也输出事件通知给应用程序。
    Filter Graph的另一个用途是将filter连在一起创建一个filter graph。
    编写一个DirectShow应用程序大体需要三个步骤:
    1.创建一个Filter Graph Manager的实例
    2.使用Filter Graph Manager创建一个filter graph,此时,需要已经具备所有必需的filter。
    3.使用Filter Graph Manager控制filter graph和通过这些filter的流,在这个过程中,应用程序会收到Filter Graph Manager发送的事件。
    完成这些后,应用程序需发布这个Filter Graph Manager和所有的filter。
2.3. 播放一个文件
    这一章以本节这个有趣的例子来结束,这个例子是一个播放音频或视频文件的简单控制台程序。程序只有寥寥数行,但却展示了DirectShow编程的强大能力。
    正如上一节所讲的创建DirectShow应用程序的三个步骤,第一步,首先,需要调用CoInitialize来作初始化,然后调用CoCreateInstance创建Filter Graph Manager:

HRESULT hr = CoInitialize(NULL);
    if (FAILED(hr))
    {
        return;
    }

IGraphBuilder *pGraph;
    HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL,
        CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);

如上所示,类标识符(CLSID)是CLSID_FilterGraph。Filter Graph Manager由进程内DLL(in-process DLL)提供,因此参数3,dwClsContext的值为CLSCTX_INPROC_SERVER。由于DirectShow运行自由线程模式(free-threading model),所以你同样可以使用COINIT_MULTITHREADED参数来调用CoInitializeEx。
    第二步是创建filter graph,调用CoCreateInstance得到的IGraphBuilder接口包含了大部分创建filter graph的方法。在这个例子中还需要另外两个接口:IMediaControl和IMediaEvent。
    IMediaControl控制数据流,它包含开启和停止graph的方法;IMediaEvent包含从Filter Graph Manager获取事件的方法,在这个例子中,这个接口用来得到回放结束事件。
    所有这些接口由Filter Graph Manager提供,使用得到的IGraphBuiler接口指针来查询得到。

    IMediaControl *pControl;
    IMediaEvent   *pEvent;
    hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
    hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);

现在你可以创建filter graph了,对于文件回放只需要一个简单的调用:

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

IGraphBuilder::RenderFile方法创建了一个能够播放指定文件的filter graph,事实上,原本需要做的一些如创建filter实例及将这些filter连接起来的工作,都由这个方法自动完成了,如果是视频文件,这个filter graph看起来应该是这个样子:
    [file source]->[如果是缩格式,这里是个解码器]->[Video Renderer]
    要开始回放,调用IMediaControl::Run方法:

      hr = pControl->Run();

当filter graph运行时,数据经过各个filter最后回放为视频或音频。回放发生在一个单独的线程中。你可以通过调用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;

// Initialize the COM library.
    HRESULT hr = CoInitialize(NULL);
    if (FAILED(hr))
    {
        printf("ERROR - Could not initialize COM library");
        return;
    }

// Create the filter graph manager and query for interfaces.
    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);

// Build the graph. IMPORTANT: Change this string to a file on your system.
    hr = pGraph->RenderFile(L"C://Example.avi", NULL);
    if (SUCCEEDED(hr))
    {
        // Run the graph.
        hr = pControl->Run();
        if (SUCCEEDED(hr))
        {
            // Wait for completion.
            long evCode;
            pEvent->WaitForCompletion(INFINITE, &evCode);

// Note: Do not use INFINITE in a real application, because it
            // can block indefinitely.
        }
    }
    pControl->Release();
    pEvent->Release();
    pGraph->Release();
    CoUninitialize();
}

DirectShow编程(2)- 开始DirectShow旅程相关推荐

  1. DirectShow编程(1)- DirectShow介绍

    学习DirectShow有一段时间了,把这段学习过程中翻译出来的SDK与大家分享,同时也希望专家们指出我理解上的错误,万分感谢. 1. DirectShow介绍     DirectShow是一个wi ...

  2. DirectShow编程

    3. 关于DirectShow 3.1. DirectShow体系概述     多媒体的难题     处理多媒体有几个主要的难题:     *多媒体流包含了巨大的数据量,而这些数据都必须非常快地被处理 ...

  3. DirectShow编程实现摄像头视频捕捉

    前言 DirectShow是微软公司提供的一套在Windows平台上进行流媒体处理的开发包,与DirectX开发包一起发布. DirectShow为多媒体流的捕捉和回放提供了强有力的支持.用Direc ...

  4. DirectShow编程(3.1)- 关于DirectShow - DirectShow体系概述

    3. 关于DirectShow 3.1. DirectShow体系概述     多媒体的难题     处理多媒体有几个主要的难题:     *多媒体流包含了巨大的数据量,而这些数据都必须非常快地被处理 ...

  5. DirectShow编程(3.5) - 关于DirectShow - DirectShow中的事件通告

    3.5 DirectShow中的事件通告    这一节主要描述在directshow filter graph中事件是怎样发生的,以及应用程序如何接收事件通告并响应它们. 3.5.1 概述    一个 ...

  6. Directshow完整介绍

    最近一段时间,在编写DirectShow应用程序时常常遇到一些问题,原因是对DirectShow技术没有较全面地掌握,对各个接口间的关系以及filter与filter之间连接的内部过程等都只是一知半解 ...

  7. 一个清华学子写的关于directshow的学习心得【转】

    学习DirectShow有一段时间了,把这段学习过程中翻译出来的SDK与大家分享,同时也希望专家们指出我理解上的错误,万分感谢. 1. DirectShow介绍     DirectShow是一个wi ...

  8. DirectX和DirectShow介绍和区别

    1.DirectX是什么 DirectX是微软推出的一套基于Windows系统的多媒体应用程式接口APIs函式.在开发中,DX分为两个部分,一个是运行库,通过DX编译出来的程式必须要有运行库的支持,另 ...

  9. DirectShow组件原理分析及应用

    1 DirectX简介 DirectX是Microsoft公司为游戏和其他高性能多媒体应用所提供的一套底层应用程序编程接口.这些接口包括对二维和三维图形,声效和音乐,输入设备以及多玩家网络游戏等的支持 ...

最新文章

  1. 【已解决】Navicat 远程连接 Linux服务器上的MySQL数据库
  2. 360互联网技术训练营第七期 - “遇见”PIKA
  3. oracle获取sysdba权限,Oracle 学习笔记: SYSDBA登陆权限问题
  4. 写一个生产者消费者的例子
  5. 写给自己,关于对纯技术的追求,以及为了金钱与前途的技术追求
  6. Golang高效实践之array、slice、map实践
  7. linux常见命令用法之(一)
  8. CPC客户端报错 error
  9. 使用python实现嵌套压缩包解压
  10. 大创人人有,我怎么才能拿到国家级?
  11. 正则表达式匹配以xx开头以xx结尾
  12. Win11使用CAD卡顿或者致命错误怎么办?Win11无法正常使用CAD
  13. FAT32、NTFS、exFAT格式的区别
  14. com.lbx:xTools
  15. Springboot 使用 sendgrid发送邮件
  16. Linux安装Googlepinyin
  17. 《数据库系统概论》第四版课后习题答案
  18. 社群营销运营分类包括哪些内容
  19. JAVA服务端实现页面截屏(附代码)
  20. 郑州国防学校计算机网络技术,郑州国防科技学校2021年招生计划

热门文章

  1. 12个开源的后台管理系统
  2. vue 实现上拉加载
  3. 有关推挽输出、开漏输出、复用开漏输出、复用推挽输出
  4. C sharp(#)中的float,double, Single,Double关键字
  5. sqlmap 注入教程 常用命令大全
  6. 服务器之间的文件传输
  7. java和易语言对比_国外流行排行榜编程语言和易语言相比较的优势和劣势
  8. PHP中 die() 和 exit() 的区别
  9. 机器学习(特征选择与稀疏学习)
  10. BIND+Mysql实现DNS轮询泛解析和IP视图