微軟做了很多的介面以便和directx兄弟能配合編程,我們再ildasm下面可以看到,只有一個名為FilgraphManagerClass的class,其實仔細看了一下,也沒有多少大的函數,DirectX在抽象上分了4層,
硬體/網路層:放置有多媒體裝置,包括圖形加速器、音效卡、輸入裝置以及網路通訊裝置等;
DirectX基礎層:為映像、聲音和裝置提供多媒體基本服務;
DirectX媒體層:
為動畫製作、音頻和視頻等提供API功能;
組件層:包括ActiveX控制和應用,它利用DirectX的API功能的優勢為使用者提供多媒體服務。
DirectShow
就是建立在DirectX媒體層之上的技術,其前身是ActiveMovie2.0。它以
一組API函數或ActiveX控制項出現,用途是讓開發人員能夠在網路上傳遞高品質的音頻和視頻訊號。值得一提的是,DirectShow為我們提供了一個
開放式的開發環境,我們可以根據自己的需要定製組件。
DirectShow
定義了如何利用標準組件來處理流媒體資料,這些組件稱為過濾器。過濾器帶有輸入、輸出針角
(pin),或二者兼而有之。在DirectShow技術中處於最核心位置的就是作為"過濾器"的可插入標準組件,它是執行特定任務的COM對象。過濾器
又可被細分為源過濾器(Source filter)、變換過濾器(Transform filter)、表現過濾器(Renderer filter)
等。過濾器通過向檔案讀寫、修改資料和顯示資料到輸出裝置上來操作流媒體。過濾器的針腳通過協商來決定它們將支援何種形式多媒體。由於
DirectShow支援可重構的過濾器圖表結構,所以使用相同的軟體組件可以播放多種類型的媒體,開發人員可以通過定義自己的過濾器來擴充
DirectShow對媒體的支援功能。
源過濾器用來從資料來源擷取資料,並將資料傳送到過濾器圖表中,這裡的資料來源可以是攝像機、網際網路、磁碟檔案等;
轉換過濾器用來擷取、處理和傳送媒體資料,它包括分離視頻和音訊分解變換過濾器(Splitter transform filter)、解壓視頻
資料的視頻轉換過濾器(Video transform filter)、解壓音頻資料的音頻轉換過濾器
(Audio transform filter)
表現過濾器用來在硬體上表現媒體資料,如顯卡和音效卡,或者是任何可以接受媒體資料的地方,如磁碟檔案。它包括用來顯示映像的視頻表現過濾器
(Video renderer filter)、將音頻資料送到音效卡上去的音頻表現過濾器(Audio renderer filter)。
簡單的說,就是讀取資訊,利用一種“針”技術,轉化變化,然後輸出到硬體。
DirectShow
建立在COM組件技術基礎上,所以開發DirectShow程式必須要掌握COM組件技
術。DirectShow與COM緊密相連,它所有的組件和功能都由COM介面來構造和實現,其開發方式相當靈活,沒有固定的模式,通常隨不同的需要使用
不同的COM介面。但是其中幾個重要的介面確實經常需要用到的:IGraphBuilder介面,這是最為重用的COM介面,用來建立
Filter Graph Manager;IMediaControl介面,用來控制流程媒體在濾波器圖表(Filter Graph)中的流動,例如流
媒體的啟動和停止;IMediaEvent介面,該介面在Filter Graph發生一些事件時用來建立事件的標誌資訊並傳送給應用程式。
一個典型的DirectShow應用程式的開發通常遵循的步驟為:
1)通過API函數CoCreateInstance()建立一個Filter Graph Manager 執行個體;
2)通過調用QueryInterface ( )函數來擷取Filter Graph 和IMediaEvent組件的指標;
3)對Filter Graph進行控制和對事件作出響應。
例如:首先產生一個名為MediaPlay的單文檔應用程式,定義一個名字為MediaPlay的函數,該函數的具體實現代碼為:
void PlayMovie(LPTSTR lpszMovie)
{
IMediaControl *pMC = NULL;
IGraphBuilder *pGB = NULL;
IMediaEventEx *pME = NULL;
long evCode; // something to hold a returned event code
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,
IID_IMediaControl, (void **)&pMC);
hr = pMC->QueryInterface(IID_IGraphBuilder, (void **)&pGB);
hr = pMC->QueryInterface(IID_IMediaEventEx, (void **)&pME);
hr = pGB->RenderFile(lpszMovie, NULL);
hr = pMC->Run();
hr = pME->WaitForCompletion(INFINITE, &evCode);
if(pMC)pMC->Release();
if(pGB)pGB->Release();
if(pME)pME->Release();
}
上述代碼中,CoCreateInstance()函數建立了一個過濾器圖表(Filter Graph)對象,並返回一個媒體控制
(ImediaControl)介面,這個介面通過過濾器來實現播放、暫停、停止等媒體放映功能,但是這時候圖表對象並不包含具體的過濾器,因為此時
DirectX並不清楚需要播放何種類型的媒體;接下來建立一個圖表構建介面,該介面可以實現建立過濾器圖表、向圖表對象添加、刪除各種過濾器、列舉當前
過濾器圖表中所有的過濾器、連通圖對象中的各個過濾器等功能;本例中使用了IGraphBuilder 介面的RenderFile()函數,告訴
DirectX需要播放的媒體檔案名,此時IgraphBuilder對象介面根據多媒體檔案的類型,自動向過濾器圖表添加播放該類型媒體所需的的各種過
濾器,並實現其串連。
最後,函數調用ImediaControl介面對象的Run()函數,就可以開始播放媒體檔案了。為了實現從頭至尾的順序播放完多媒體檔案,需要調用
IMediaEventEx 對象介面的WaitForCompletion()阻塞函數的運行,直到媒體檔案結束後才可以釋放對象、結束函數的運
行。
附錄:
所有的事件通報碼:
EC_ACTIVATE 視頻視窗被啟用或者轉為非啟用狀態
EC_BUFFERING_DATA 過濾圖形包含緩衝資料
EC_CLOCK_CHANGED 參考時鐘被改變
EC_CLOCK_UNSET 時鐘提供者被斷開
EC_COMPLETE 所有資料被渲染完畢
EC_DEVICE_LOST 一個隨插即用裝置被移除或者變為有效.
EC_DISPLAY_CHANGED 顯示模式被改變
EC_END_OF_SEGMENT 到達段的末尾.
EC_ERROR_STILLPLAYING 一個非同步命令失敗
EC_ERRORABORT 一個操作被放棄
EC_EXTDEVICE_MODE_CHANGE 不支援
EC_FULLSCREEN_LOST 一個視頻渲染視窗被切換出全螢幕模式.
EC_GRAPH_CHANGED 過濾器圖被改變
EC_LENGTH_CHANGED 源的長度被改變.
EC_NEED_RESTART 過濾器請求過濾圖重新開始.
EC_NOTIFY_WINDOW 通報一個視頻渲染視窗的過濾器
EC_OLE_EVENT 過濾器傳遞一個字串給應用程式。.
EC_OPENING_FILE 過濾圖開啟一個檔案,或者已經完成了開啟檔案操作
EC_PALETTE_CHANGED 視頻調色盤被改變.
EC_PAUSED 一個暫停請求被處理.
EC_QUALITY_CHANGE 過濾圖為了品質控制丟楨
EC_REPAINT 一個視頻渲染器要求重繪.
EC_SEGMENT_STARTED 一個新段開始
EC_SHUTTING_DOWN 過濾器圖被關閉
EC_SNDDEV_IN_ERROR 一個音訊裝置的輸入引腳錯誤.
EC_SNDDEV_OUT_ERROR 一個音訊裝置的輸出引腳錯誤.
EC_STARVATION 過濾器沒有得到足夠的資料.
EC_STATE_CHANGE 過濾器圖狀態改變
EC_STEP_COMPLETE 一個過濾器執行了單楨漸進
EC_STREAM_CONTROL_STARTED 流量控制開始命令產生效果.
EC_STREAM_CONTROL_STOPPED 一個流量控制的停止命令產生效果
EC_STREAM_ERROR_STILLPLAYING 在流中產生了一個錯誤,但流還是在運行中.
EC_STREAM_ERROR_STOPPED 一個流因錯誤而停止
EC_TIMECODE_AVAILABLE 不支援
EC_USERABORT 使用者中斷回放.
EC_VIDEO_SIZE_CHANGED 本地視頻尺寸改變.
EC_WINDOW_DESTROYED 視頻渲染器被銷毀,或者從過濾器圖中移除.