27
Introduction to DirectShow Qing [email protected] (Email/MSN) 2007/1/12

Introduction To Direct Show

Embed Size (px)

Citation preview

Page 1: Introduction To  Direct Show

Introduction to DirectShowIntroduction to DirectShow

[email protected]

(Email/MSN)2007/1/12

Page 2: Introduction To  Direct Show

何謂 DirectShow ?何謂 DirectShow ?

DirectShow 是 DirectX 家族中的一支 除了 DirectShow 之外, DirectShow 尚包括了

DirectPlay DirectDraw Direct3D DirectMusic

DirectShow 的用途在於多媒體資訊的呈現 視訊 音訊

Page 3: Introduction To  Direct Show

DirectShow 的應用範圍DirectShow 的應用範圍

多媒體訊息的輸入 麥克風 攝影機 檔案 網路串流

多媒體訊息的剖析 多媒體訊息的編碼,解碼 多媒體訊息的撥放

音訊視訊呈現 多媒體訊息的儲存

Page 4: Introduction To  Direct Show

使用 DirectShow 必備使用 DirectShow 必備

C/C++/VB/C# Windows COM 元件的使用

Page 5: Introduction To  Direct Show

DirectShow 架構的優點DirectShow 架構的優點

元件化,可重用性高 各種用途的元件,都化身為標準的 Filter ,具備相同的介面,容易搭接各式 Filter

極具彈性,透過對 Filter 的客製及組裝,可以達成各式的目的

Page 6: Introduction To  Direct Show

DirectShow 核心元件DirectShow 核心元件

IFilterGraph 每個撥放結構都是用一個 IFilterGraph 所描述

IGraphBuilder 建立、控制 IFilterGraph 的元件

IBaseFilter DirectShow 中所有的 Filter 都實作的介面

IPin 代表多媒體訊息在 IFilterGraph 中流動的接腳 每個 IBaseFilter 都有一個以上的 IPin

IMediaControl 控制多媒體訊息撥放行為的元件

IMediaEvent 取得多媒體訊息撥放時的事件

Page 7: Introduction To  Direct Show

一個最簡單的 DirectShow 範例( DSFilePlayer.cpp)一個最簡單的 DirectShow 範例( DSFilePlayer.cpp)

目的:從檔案執行撥放指定的多媒體檔案 步驟:

1. 初始化 COM2. 建立 IFilterGraph 的 instance3. 取得 IMediaControl 的介面( IFilterGraph 實作了

IMediaControl 的介面)4. 取得 IMediaEvent ( IFilterGraph 實作了

IMediaEvent 的介面)5. 透過 IMediaControl 智慧型的建立 Filter Graph 的內容6. 透過 IMediaControl 啟動撥放7. 透過 IMediaEvent 等待撥放結束

Page 8: Introduction To  Direct Show

初始化 COM初始化 COM

HRESULT hr;

hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);

if( FAILED(hr) )

{

CoUninitialize();

return hr;

}

Page 9: Introduction To  Direct Show

建立 IFilterGraph 的 instance建立 IFilterGraph 的 instance

IFilterGraph *pFilterGraph = NULL;

//

hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,IID_IFilterGraph, (void**) &pFilterGraph);

Page 10: Introduction To  Direct Show

取得 IMediaControl/IMediaEvent 的介面取得 IMediaControl/IMediaEvent 的介面

IMediaControl *pMC = NULL;

IMediaEvent *pME = NULL;

hr = pFilterGraph->QueryInterface(IID_IMediaControl, (void **) &pMC);

if( FAILED(hr) )

{

return hr;

}

hr = pFilterGraph->QueryInterface(IID_IMediaEvent, (void **) &pME);

if( FAILED(hr) )

{

pFilterGraph->Release();

pMC->Release();

return hr;

}

Page 11: Introduction To  Direct Show

建立 Filter Graph/ 撥放 /等待停止建立 Filter Graph/ 撥放 /等待停止

OAEVENT oEvent;hr = pME->GetEventHandle(&oEvent);if( SUCCEEDED(hr) ){

hr = pMC->RenderFile(fileName);if( SUCCEEDED(hr) ){

hr = pMC->Run();if( SUCCEEDED(hr) ){

LONG levCode;hr = pME->WaitForCompletion(INFINITE,

&levCode);}

}}

Page 12: Introduction To  Direct Show

何謂 Filter Graph ?何謂 Filter Graph ?

*Render WMV9時會自動建立的 Filter Graph

*Render MPEG時會自動建立的 Filter Graph

Output Pin Input Pin

分流

Renderer

Source Filter

Splitter

Page 13: Introduction To  Direct Show

何謂 Filter ?何謂 Filter ?

一個 Filter 具備一個以上的 Pin Pin 依多媒體訊息流動的方向可分為 Input Pin 或 Output

Pin Filter 的 Input Pin ,代表對此 Filter 是訊息流入的 Pin Filter 的 Outut Pin ,代表對此 Filter 是訊息流出的 Pin

Page 14: Introduction To  Direct Show

何謂 Pin何謂 Pin

Pin 是 DirectShow 中多媒體訊息藉以流經的元件 Pin 是 DirectShow 中,兩個 Filter 相接的介面 每個 Pin 都有可以接受的 Media Type

每個 Media Type 都有一個 major type例如 MEDIATYPE_Video 或 MEDIATYPE_Audio

每個 Media Type 都有一個 minor type例如 MEDIASUBTYPE_RGB32

在 Filter Graph 中要接在一起的兩個 Filter ,其中一個的 Output Pin 可接受的 media type 必須和另一個 Filter的 Input Pin 可接受的 media type 相符

Page 15: Introduction To  Direct Show

Filter Graph 的建立Filter Graph 的建立

智慧型連接需要的 Filter 手動建立

自己產生所需的各種 Filter 依據需求把要連接在一起的兩兩 Filter 接在一起

把 Filter A 的 Output Pin 接到 Filter B 的 Input Pin

Page 16: Introduction To  Direct Show

如何開始 DirectShow 應用程式的開發如何開始 DirectShow 應用程式的開發

安裝 SDK DirectX SDK ,或 Platform SDK

將 SDK 的 include 目錄加至 Visual Studio 的 include 目錄中 將 SDK 的 lib 目錄加至 Visual Studio 的 lib 目錄中 build DirectX SDK 中附的 DirectShow BaseClasses

例: DirectX 9.0 DXSDK\Samples\C++\DirectShow\BaseClasses

產生 BaseClasses\Debug\strmbasd.lib ( debug mode 用) 產生 BaseClasses\Release\strmbase.lib ( release mode 用)

Page 17: Introduction To  Direct Show

如何設定 DirectShow 應用程式的專案如何設定 DirectShow 應用程式的專案

在專案設定中設定 C/C++ 及 Linker 的選項 C/C++

GeneralAdditional Include Directories ,加上: BaseClasses\

PreprocessorPreprocessor Definitions ,加上: _WIN32_DCOM

Linker General

Additional Library Directories ,加上: BaseClasses\Debug或 BaseClasses\Release (視 debug mode 或 release 而定,加上這兩個目錄的原因是要將 Input 中指定的 strmbasd.lib或 strmbase.lib 加入)

InputAdditional Dependencies ,加上: strmbasd.lib (或

strmbase.lib ,視 debug mode 或 release 而定) winmm.lib

Page 18: Introduction To  Direct Show

BaseClasses 及 DirectShow 範例BaseClasses 及 DirectShow 範例

雖然 BaseClasses 被放在 DirectShow 的範例程式中,但其實提供了對於 DirectShow COM 介面的高階實作

基於 BaseClasses ,繼承其類別,對於實作 DirectShow中的各式 Filter 有相當大的幫助

在撰寫各式 Filter 時,建議參考 DirectShow 中的範例程式 例: DirectX 9.0 DXSDK\Samples\C++\DirectShow\Filters

Page 19: Introduction To  Direct Show

範例程式中示範的基本 Filter 類型 (1/2)範例程式中示範的基本 Filter 類型 (1/2)

Async : Pull mode 的 Source Filter Source Filter 是提供多媒體訊息的 Filter (起點) Pull Source Filter 是基於另一 Filter 的 Input Pin 的請求,將資料餵至自己的 Output Pin

Dump : Renderer Filter Renderer Filter 是負責呈現多媒體訊息的 Filter (終點)

EZRGB24 : Image Processing Filter 針對多媒體訊息進行加工的 Filter

Grabber : SampleGrabber Filter 擷錄 Filter Graph 中流動的多媒體訊息用的 Filter

Page 20: Introduction To  Direct Show

範例程式中示範的基本 Filter 類型 (2/2)範例程式中示範的基本 Filter 類型 (2/2)

INFTee : Infinite Pin Tee Filter Tee Fitler 是分接用的 Filter ,例如一個輸出 Pin 變成兩個輸出 Pin ,將多媒體訊息複製成多份,提供給後續的多個 Filter

INFTee 可將一個 Input Pin 的內容,複製至不限個數的 Output Pin

NullInPlace : In-Place Transform Filter 於原地(不配置額外的記憶體)處理多媒體訊息的

Filter NullNull : Minimal Null Filter

示範最小的 Filter PushSource : Push Source Filter

Push Source Filter 是自己主動將資料餵至自己的Output Pin 的 Filter

Page 21: Introduction To  Direct Show

多媒體呈現應用時常用到的 Push Source Filter多媒體呈現應用時常用到的 Push Source Filter

QPushSource 是一個通用的範例 參考 QPushSource.cpp, QPushSource.h,

QPushSourceGuids.h 繼承後覆寫,或直接改寫 QPushSourceStream 的

HRESULT GetMediaType(CMediaType *pMediaType)

HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pRequest)

改寫 CLSID_QPushSource

Page 22: Introduction To  Direct Show

HRESULT GetMediaType(CMediaType *pMediaType)HRESULT GetMediaType(CMediaType *pMediaType)

當兩個 Pin 之間做連接的動作時,會呼叫GetMediaType()判斷兩 Filter 是否能夠相接 取決在回傳的 pMediaType 是否相容

如何改寫 GetMediaType() ? 根據你的 Push Source Filter會回傳的多媒體類型,適時的填入

例如產生 RGB32 的 Video 訊息pMediaType->SetType(& MEDIATYPE_Video);pMediaType->SetSubtype(&

MEDIASUBTYPE_RGB32);pvi->bmiHeader.biCompression = BI_RGB;pvi->bmiHeader.biBitCount = 32;

Page 23: Introduction To  Direct Show

HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pRequest)HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pRequest)

Push Source Filter 的下游 Filter會呼叫DecideBufferSize()來得知究竟應該準備多大的 buffer空間來接收 Push Source Filter傳入的資料

例如,對 640x480 的 RGB32 資料來說: pRequest->cbBuffer = 640*480*4;

Page 24: Introduction To  Direct Show

如何使用 QPushSource如何使用 QPushSource

產生 QPushSource 的 instance pPushSource = (QPushSource*)

QPushSource::CreateInstance(NULL, &hr); 由 QPushSource 的 Output Pin 開始 Render FilterGraph

Page 25: Introduction To  Direct Show

使用 QPushSource 的步驟使用 QPushSource 的步驟

1. 設定或繼承並覆寫 QPushSourceStream::GetMediaType 指定正確的 Media Type 及 Format

2. 設定或繼承並覆寫QPushSourceStream::DecideBufferSize 指定足夠大的 buffer 大小

3. 修改範例 main.cpp 中的 HowToAddANewFrame() ,把多媒體訊息加入至 QPushSource 中的 queue

Page 26: Introduction To  Direct Show

main.cpp: 示範如何運用 QPushSourcemain.cpp: 示範如何運用 QPushSource

// 初始化 COM

CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);

// 產生 QPushSource 的 instance

pPushSource = (QPushSource*) QPushSource::CreateInstance(NULL, &hr);

// 從 QPushSource開始 Render整個 Filter Graph

hr = RenderSourceFilter(pPushSource, &pFilterGraph);

//啟動 Filter Graph的運作,並等待結束hr = RunGraphAndWaitFormCompletion(pFilterGraph);

Page 27: Introduction To  Direct Show

Q&AQ&A

Thanks