DirectShow初探

来源:互联网 发布:11.11淘宝销售额 编辑:程序博客网 时间:2024/04/30 08:33

可能到现在为止,还没有哪个玩过游戏的人没有接触过Microsoft的DirectX的。因为现今大多数的游戏都是用DirectX开发出来的。

 

相比之下,DirectShow只是DirectX的一个子集。DirectX中还包括DirectSound、Direct3D等集合。DirectShow主要用来处理一些与音视频有关的多媒体任务,比如音视频采集、回放等。过年回来后,在一个项目中要求在WIN32下采集视频信号,以前做过GDI的,不过效率低下,而且效果也很烂,所以决定加速,怎样加速,答案就在DirectShow。

 

1、DirectShow的结构

我们知道,Windows操作系统只用了CPU中的两个特权级(0和3)。0是内核模式,它可以直接访问硬件;3是用户模式,它不能直接访问硬件。DirectShow的基本工作单元是Filter(过滤器),过滤器的就像一个筛子,它一般有输入引脚(PIN)和输出引脚,数据从输入引脚流入而从输出端口流出。DirectShow中的过滤器一般分为下列3类:

 

       1) Source Filter (用于提供原始的多媒体数据,比如一个视频文件)

       2)Transform Filter(用于处理从Source Filter 传过来的多媒体数据,比如MPEG-4解码器)

       3)Rendering Filter(用于显示、回放和存储多媒体数据给用户,比如文件写入器)

 

要完成特定的多媒体功能,必须用相应的Filter组成特定的Filter Graph。多媒体数据在Graph中流动,到达Rendering Filter时回放给用户。

 

用户应用程序怎么样控制Filter Graph呢?他必须创建一个相应的Filter Graph Manager,应用程序向Manager发送相应的命令(Command),然后从Manager那接收相应的Event,最后做出相应的响应。

 

每个Filter都有操作硬件的能力,这就是为什么DirectShow能如此高效的使用多媒体了。

 

DirectShow的结构原理图如下:

 

2、使用DirectShow编写一个简单的应用程序

 

      使用DirectShow编写应用程序的一般步骤如下:

      1)根据系统完成的功能构建相应的Filter Graph。

      2)构建Graph中的每个Filter,并将它们连接起来。

      3)创建Filter Graph Manager,运用Application控制Manager,从而控制整个的流程。

       4)DirectShow是基于COM(组件对象模型)的,所以在编写Filter前必须初始化COM库。

 

      下面是一个完整的播放AVI文件的小程序,其中的注解说明了编程的步骤。

 

#include <stdio.h>
#include <dshow.h>    //DirectShow必须包含的头文件,LIB库为Strmiids.lib 和 Quartz.lib

int main()
{
 IGraphBuilder *pGraph = NULL;      //  用于创建Filter Graph的接口
 IMediaControl *pControl = NULL;    //  用于向Filter Graph Manager发送Command
 IMediaEvent   *pEvent = NULL;        //   用于接收Filter Graph Manager发出的Event

 // Initialize the COM library.
 HRESULT hr = CoInitialize(NULL);   //初始化COM Library

 if( FAILED(hr) )
 {
  fprintf(stderr,"could not init the COM library!");
  return 0;
 }

//创建Filter Graph Manager

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

 if( FAILED(hr) )
 {
  fprintf(stderr,"could not create Filter Graph Manager!");
  return 0;
 }

 //查询并获得接口指针
 hr = pGraph->QueryInterface(IID_IMediaControl,(void **)&pControl);
 hr = pGraph->QueryInterface(IID_IMediaEvent,(void **)&pEvent);

 // RenderFile库函数是少数几个能够自动创建Graph的成页,所以这里省去了创建Graph这一步
 hr = pGraph->RenderFile(L"e://football.avi",NULL);

 if( SUCCEEDED(hr) )
 {
  hr = pControl->Run();

  if( SUCCEEDED(hr) )
  {
   // 等待视频结束
   long evCode;
   pEvent->WaitForCompletion(INFINITE, &evCode);

   // 无限等待

  }
  
 }

 pControl->Release();
 pEvent->Release();
 pGraph->Release();

//释放接口

 CoUninitialize();   //御载COM 库


 return 0;

原创粉丝点击