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; }

相關文章
相關標籤/搜索