DirectShow初探

可能到如今为止,尚未哪一个玩过游戏的人没有接触过Microsoft的DirectX的。由于现今大多数的游戏都是用DirectX开发出来的。html

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

一、DirectShow的结构小程序

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

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

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

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

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

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

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

DirectShow的结构原理图以下:

二、使用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; }

相关文章
相关标签/搜索