DirectX組件之---DirectShow介紹

1. DirectShow介紹
    DirectShow是一個windows平臺上的流媒體框架,提供了高質量的多媒體流採集和回放功能。它支持多種多樣的媒體文件格式,包括ASF、MPEG、AVI、MP3和WAV文件,同時支持使用WDM驅動或早期的VFW驅動來進行多媒體流的採集。DirectShow整合了其它的DirectX技術,能自動地偵測並使用可利用的音視頻硬件加速,也能支持沒有硬件加速的系統。
    DirectShow大大簡化了媒體回放、格式轉換和採集工作。但與此同時,它也爲用戶自定義的解決方案提供了底層流控制框架,從而使用戶可以自行創建支持新的文件格式或其它用途的DirectShow組件。
    以下是幾個使用DirectShow編寫的典型應用:DVD播放器、視頻編輯應用、AVI到ASF轉換器、MP3播放器和數字視頻採集應用。
    DirectShow是建立在組件對象模型(COM)上的,因此當你編寫DirectShow應用時,你必須具備COM客戶端程序編寫的知識。對於大部分的應用,你不需要實現自己的COM對象,DirectShow提供了大部分你需要的DirectShow組件,但是假如你需要編寫自己的DirectShow組件,你還需要具備編寫COM組件的知識。
1.1. DirectShow支持的格式
    DirectShow是一個開放的框架,因此只要有合適的filter來分析和解碼,它可以支持任何格式。DirectShow默認支持以下的文件類型和壓縮格式:
    注:打*號的需要Windows Media Format SDK支持
    文件類型:
      Windows Media? Audio (WMA)*
      Windows Media? Video (WMV)*
      Advanced Systems Format (ASF)*
      Motion Picture Experts Group (MPEG)
      Audio-Video Interleaved (AVI)
      QuickTime (version 2 and lower)
      WAV
      AIFF
      AU
      SND
      MIDI
    壓縮格式:
      Windows Media Video*
      ISO MPEG-4 video version 1.0*
      Microsoft MPEG-4 version 3*
      Sipro Labs ACELP*
      Windows Media Audio*
      MPEG Audio Layer-3 (MP3) (decompression only)
      Digital Video (DV)
      MPEG-1 (decompression only)
      MJPEG
      Cinepak
    微軟自己沒有提供MPEG2解碼器,一些可用的DirectShow MPEG2硬件或軟件解碼器是由第三方提供的。
1.2. 常見問題集(摘錄)
1.2.1. 一般問題

    *DirectShow支持哪些操作系統?
      DirectShow支持Windows9X、Windows2000、Windows Me和Windows XP。
   
    *使用DirectShow需要多少COM知識?
      應用程序開發者只需要基本的COM組件知識:實例化COM組件、調用接口、管理接口的引用計數。Filter開發者則需要更多。
     
    *有與DirectShow兼容的硬件列表(HCL)嗎?
      沒有。如果硬件兼容DirectShow,DirectShow會使用它們,如果沒有兼容的硬件,DirectShow使用GDI繪製視頻,以及使用WaveOut系列多媒體API來播放音頻。
     
    *可以使用哪些語言來編寫DirectShow應用?
      DirectShow主要爲C/C++開發設計。Visual Basic只能使用其中的很小一部分。可以通過MS JScript或VB Script來支持基於腳本的DVD和TV應用。也可能用Delphi來編寫,但SDK文檔不提供這方面的內容。
     
    *DirectShow會通過託管代碼實現嗎?
      目前還沒有這個計劃。DirectX SDK提供了有限的使用音視頻回放類的託管回放功能,你可以使用COM interop創建託管代碼的DirectShow客戶端應用,但是因爲性能上的原因,不推薦創建運行在CLR上的filter。

    *DirectShow開發需要什麼樣的編譯器
      任何能夠產生COM對象的編譯器都可以。
     
    *DirectShow和DirectX的其它組件的關係
      DirectShow和DirectX的其它組件在內部進行聯繫。DirectShow在硬件的支持下使用DirectSound和DirectDraw。Video Renderer和Overlay Mixer使用DirectDraw 3和DirectDraw5表面(surfaces)。Video Mixing Renderer 7(只支持WINXP)使用DirectDraw7表面。Video Mixing Renderer 9使用最新的(目前是Directx9)Direct3D API函數。即便是某個應用程序包含了DirectX其它組件,你也不必使用其它組件的API去編寫它。參考SDK的例子:Texture3D Sample。
     
    *DirectShow與ActiveMovie的關係?
      ActiveMovie是DirectShow原來的名稱,現已不再使用,但是一部分API仍保留了"AM"的前綴,比如AM_MEDIA_TYPE和IAMVideoAccelerator。
     
    *DirectShow是限於多媒體應用嗎?
      DirectShow默認包含的組件主要是爲音視頻流設計的,但是,DirectShow框架已經成功地用於其它數據流的解決方案中。
     
    *GraphEdit工具有源碼嗎?GraphEdit.exe是否可再發布?
      沒有源碼,不可再發布。
     
    *DMO可以代替DirectShow filter嗎?
      在編寫編碼器、解碼器、效果器應用時,鼓勵用DMO代替DirectShow filter。在其它的應用中,使用DirectShow filter可能會比較合適。
     
1.2.2. 程序編寫問題
    *如何設置編譯環境,需要哪些頭文件和庫?
      參考"設置編譯環境"章節
     
    *GraphEdit列示了很多沒有文檔支持的filter,它們都是些什麼?
      GraphEdit枚舉了所有作爲filter類型註冊在系統中的filter,包括由第三方應用程序安裝的filter,以及其它微軟技術如Windows Media或NetMeeting安裝的,另外,一些DirectShow filter被用來做硬編碼或硬解碼驅動的外殼。Microsoft H.263 Video Codec用於NetMeeting,不再被DirectShow支持。
   
    *如何知道DirectShow已經被安裝?
      調用CoCreateInstance創建一個Filter Graph Manager實例,如果成功,表示DirectShow已經被安裝,下面是一個例子:

      IGraphBuilder *pGraph;

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


          
    *如果不通過屬性設置頁來更改filter的設置?
      當然是通過filter提供的接口羅。如果沒有提供,就沒有辦法啦
     
    *DirectShow能通知應用程序當前回放位置嗎?
      不提供回調來通知位置,需要使用一個計時器定時調用IMediaSeeking::GetCurrentPosition方法來得到當前回放位置。
     
    *filter運行在哪個特權級別下?
      運行在Ring 3特權級別下,某些流控制驅動(如音視頻採集驅動)運行在Ring 0特權級別下。
     
    *需要一個Kernel調試器嗎?
      這依據具體的項目。安裝DirectX調試運行時庫(DirectX debug runtime library)意味着安裝調試驅動(Debug driver)和其它核心組件(kernel mode component),因此如果你的應用程序在其中的某個組件中產生了一個調試斷言(debug assert),你的機器就會自動重啓除非你擁有一個kernal調試器。
     
    *DEFINE_GUID宏是怎麼工作的?
      使用DEFINE_GUID宏可以讓你通過包含同一個頭文件來定義GUID值而不必使用extern關鍵詞。比如,你的工程中有三個源文件:src1.cpp,src2.cpp,src3.cpp,它們都使用一個相同的GUID值,而爲了保證一致性,這個GUID只能在你的工程中定義一次,這時,其它的源文件必須定義外部引用來使用它。用了DEFINE_GUID,你可以使用在所有源文件中包含同一個頭文件,在頭文件中這樣定義GUID:

    DEFINE_GUID(CLSID_MyObject,
         0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);


            這個例子中GUID爲0,實際編程中請用Guidgen工具來產生一個GUID,在其中的一個源文件中,在你的頭文件前包含initguid.h,如:

   // Src1.cpp
 #include 
 #include "MyGuids.h"
 
 // Src2.cpp
 #include "MyGuids.h" 

// Src3.cpp #include "MyGuids.h"


     
在沒有包含Initguid.h的地方,DEFINE_GUID宏創建外部引用來使用GUID值,在包含Initguid.h的地方,DEFINE_GUID重定義DEFINE_GUID宏以產生GUID的定義。
如是沒有在任何地方添加Initguid.h,你會得到一個鏈接錯誤:"unresolved external symbol." ,如果同樣的GUID包含Initguid.h兩次,會得到編譯錯誤"redefinition; multiple initialization."要解決這些問題,請確認Initguid.h只包含一次。同樣的,不要包含Initguid.h到預編譯頭文件中去,因爲預編譯頭文件會被每個源文件包含。


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