可能到如今爲止,尚未哪一個玩過遊戲的人沒有接觸過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; }