DirectShow流媒體數據的採集及圖片的捕獲

作者: 沈浩 譚駿珊
時間: 2004-09-15
出處: ahcit
概述

  流媒體的處理,以其複雜性和技術性,一向廣受工業界的關注。特別伴隨着因特網的普及,流媒體在網絡上已廣泛應用﹐怎樣使流媒體的處理變得簡單而富有成效逐漸成爲了焦點問題。選擇一種合適的應用方案,將事半功倍。此時,微軟的DirectShow給了我們一個不錯的選擇。

  DirectShow是微軟公司在ActiveMovie和Video for Windows的基礎上推出的新一代基於COM的流媒體處理的開發包,與DirectX開發包一起發佈。目前,DirectX最新版本爲9.0。DirectShow爲多媒體流的捕捉和回放提供了強有力的支持。運用DirectShow,我們可以很方便地從支持WDM驅動模型的採集卡上捕獲數據,並且進行相應的後期處理乃至存儲到文件中。這樣使在多媒體數據庫管理系統(MDBMS)中多媒體數據的存取變得更加方便。

  DirectShow 原理及重要的接口

  1、DirectShow工作原理

  1) DirectShow的系統結構

  DirectShow的體系結構如圖1所示。


圖1 DirectShow系統
  
  DirectShow位於應用層中。它使用一種叫Filter Graph的模型來管理整個數據流的處理過程;參與數據處理的各個功能模塊叫Filter;各個Filter 在Filter Graph中按一定的順序連接成一條“流水線”協同工作。按照功能來分,Filter大致分爲三類:Source Filters、Transform Filters和Rendering Filters。Source Filters主要負責取得數據,數據源可以是文件、因特網、或者計算機裏的採集卡、數字攝像機等,然後將數據往下傳輸;Transform Fitlers主要負責數據的格式轉換、傳輸;Rendering Filtes主要負責數據的最終去向,我們可以將數據送給聲卡、顯卡進行多媒體的演示,也可以輸出到文件進行存儲。

  在DirectShow系統之上,我們看到的,即是我們的應用程序(Application)。應用程序要按照一定的意圖建立起相應的Filter Graph,然後通過Filter Graph Manager來控制整個的數據處理過程。DirectShow能在Filter Graph運行的時候接收到各種事件,並通過消息的方式發送到我們的應用程序。這樣,就實現了應用程序與DirectShow系統之間的交互。

  2) Filter概述以及連接

  過濾器(Filter)是DirectShow中最基本的概念。DirectShow是通過Filter Graph來管理Filter的。Filter Graph是Filter的“容器”,而Filter是Filter Graph中的最小功能模塊。Filter是一種COM組件,對於每個Filter,都有其自己的Pin,它是由Filter創建的COM對象。Filter通過Pin來進行他們之間的連接。Pin分爲兩種:輸出Pin和輸入Pin。輸出的Pin把Filter處理後的數據傳送到Filter的外部,而輸入Pin則是把Filter外部的數據接收到Filter中,以便Filter對這些數據進行處理。對於三種類型的Filter(Source Filter,Transform Filter,Rendering Filter)的連接圖如下:


圖2 Filter的連接

  2、DirectShow對硬件的支持原理

  大家知道,爲了提高系統的穩定性,Windows操作系統對硬件操作進行了隔離;應用程序一般不能直接訪問硬件。DirectShow Filter工作在用戶模式(User mode,操作系統特權級別爲Ring 3),而硬件工作在內核模式(Kernel mode,操作系統特權級別爲Ring 0),DirectShow解決的方法是,爲這些硬件設計包裝Filter;這種Filter能夠工作在用戶模式下,外觀、控制方法跟普通Filter一樣,而包裝Filter內部完成與硬件驅動程序的交互。這樣的設計,使得編寫DirectShow應用程序的開發人員,從爲支持硬件而需做出的特殊處理中解脫出來。DirectShow已經集成的包裝Filter,包括Audio Capture Filte(qcap.dll)、VfW Capture Filter(qcap.dll,Filter的Class Id爲CLSID_VfwCapture)、TV Tuner Filter(KSTVTune.ax,Filter的Class Id爲CLSID_CTVTunerFilter)、Analog Video Crossbar Filter(ksxbar.ax)、TV Audio Filter(Filter的Class Id爲CLSID_TVAudioFilter)等;另外,DirectShow爲採用WDM驅動程序的硬件設計了KsProxy Filter(Ksproxy.ax,)。下圖就是各個包裝Filter與硬件交互的結構圖:

應用程序
DirectShow Filter Graph
KsTune.ax
KsXbar.ax
KsCap.ax
其他普通的Filter
Stream Class
Tuner minidriverCrossbar mindriverCapture minidriverTuner,Crossbar,Capture minidriver

  3、DirectShow 的重要接口

  DirectShow採用了COM標準,所以很多重要的功能都是通過COM接口來完成。下面就列舉一些重要的DirectShow的接口。

  (1) IGraphBuilder接口

  用於構造Filter Graph的接口,建立和管理一系列的Filter,過濾和處理源媒體流。

  (2) IMediaControl接口

  用於控制多媒體流在過濾器圖表中的流動,如流的啓動和停止。

  (3) IMediaEvent接口

  用於捕獲播放過程中發生的事件,並通知應用程序,如EC_COMPLETE等。

  (4) IVideoWindow接口

  用於控制視頻窗口的屬性。

  (5) IMeadiaSeeking接口

  用於查找媒體的接口,定位流媒體,控制多媒體數據播放提供精確控制。

  (6) IBaseFilter接口

  從ImediaFilter接口繼承,用來定義一個具體的過濾器指針,並對多媒體數據進行處理。

  (7) IPin接口

  用於管理兩個過濾器之間的Pin,從而連接過濾器。

  (8) IsampleGrabberCB接口

  是Sample Grabber過濾器的一個接口,用於當流媒體數據通過過濾器時進行採樣以獲得幀圖象。


  用DirectShow來使用攝像頭,一般要求攝像頭的驅動是WDM格式的,當然,一些比較老的驅動格式DirectShow也可支持。在DirectShow中,有一個Sample Grabber過濾器,它是一個可以被插入流的過濾器,它有自己的緩衝,存放採樣。我們就可以用它來從一個視頻文件中簡單的撲獲一楨。DirectShow通過圖形過濾管理器(Filter Graph Manager)來與上層應用程序和下層的驅動進行聯繫。DirectShow通過捕獲過濾器(Capture Filter)來支持對攝像頭的捕獲,一個捕獲過濾器有多個插口(pin),其中的預覽(preview)插口可用來進行顯示禎圖象。

  1、創建圖形過濾管理器Filter Graph

  如上面原理所述,首先要創建Filter Graph:

CComPtr< IGraphBuilder > m_pGraph;
hr=m_pGraph.CoCreateInstance( CLSID_FilterGraph );

  2、連接設備

  還要創建系統枚舉器組件對象:

CComPtr<ICreateDevEnum>pCreateDevEnum;pCreateDevEnum.CoCreateInstance( CLSID_SystemDeviceEnum );

  然後使用接口方法CreateClassEnumerator ()爲指定的Filter註冊類型目錄創建一個枚舉器,並獲得IenumMoniker接口:

CComPtr< IEnumMoniker > pEm;
pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEm, 0 );

  接着在調用BindToObject()以後,可以將設備標識生成一個DirectShow Filter,將其加到Filter Graph中就可以參與工作了。

CComPtr< IMoniker > pM;
CComPtr< IPropertyBag > pBag;
hr=pM->BindToStorage(0,0,ID_IPropertyBag, (void**) &pBag );

  3、創建Sample Grabber過濾器

CComPtr< ISampleGrabber > m_pGrabber
hr=m_pGrabber.CoCreateInstance( CLSID_SampleGrabber );

  當創建好SampleGrabber以後,在Sample Grabber 過濾器連接到別的過濾器之前你必須配置它。然後查詢IsampleGrabber接口,還要設置流媒體類型:

m_pGrabber->SetMediaType();

  可以僅僅指定主媒體類型;或者主類型加子類型;或者主類型,子類型和類型格式。然後就把它加載到FilterGraph中去:

m_pGraph->AddFilter(pGrabBase,"Grabber" );

  4、查找Filter Graph 的Pin並完成後續連接。

  接下來就可以通過調用IGraphBuilder 的FindPin()接口來查找過濾管理器中的Pin接口,並通過ICaptureGraphBuilder2 中的接口RenderStream()來完成後續的連接。

hr=pCGB2->FindPin(pCap,PINDIR_OUTPUT,&PIN_CATEGORY_VIDEOPORT, NULL,FALSE,0,&pVPPin);
hr=pCGB2->RenderStream(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Video, pCap,pGrabBase,pRenderer);

  5、獲取流媒體類型並運行

  通過GetConnectedMediaType()獲取連接流媒體的類型以後,我們可以通過IsampleGrabberCB類的接口BufferCB()來把視頻的數據拷貝到自定義的緩衝區中,然後通過在緩衝區的拷貝進行視頻到圖象數據的拷貝。最後運行﹕

CComQIPtr<IMediaControl,&IID_IMediaControl > pControl = m_pGraph;
hr = pControl->Run( );

  結論

  本文討論了DirectShow的基本原理,創建Filter Graph的基本方法,以及通過DirectShow來捕獲視頻數據,然後將其保存爲自己想要的圖象,對於多媒體數據庫管理系統是一個非常有利的補充,如對考試報名的軟件系統有很強的適應性,可以降低開發成本。提高用戶的實用性。

  DirectShow技術是一個開發多媒體的行之有效的方法。在未來幾年中,DirectShow技術的發展前景相當廣闊,掌握DirectShow的技術將有重要的實用意義。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章