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, |
*如果不通過屬性設置頁來更改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到預編譯頭文件中去,因爲預編譯頭文件會被每個源文件包含。