SlideShare a Scribd company logo
Introduction to DirectShow Qing qing@cs.nthu.edu.tw (Email/MSN) 2007/1/12
何謂 DirectShow ? DirectShow 是 DirectX 家族中的一支 除了 DirectShow 之外, DirectShow 尚包括了 DirectPlay DirectDraw Direct3D DirectMusic DirectShow 的用途在於多媒體資訊的呈現 視訊 音訊
DirectShow 的應用範圍 多媒體訊息的輸入 麥克風 攝影機 檔案 網路串流 多媒體訊息的剖析 多媒體訊息的編碼,解碼 多媒體訊息的撥放 音訊視訊呈現 多媒體訊息的儲存
使用 DirectShow 必備 C/C++/VB/C# Windows COM 元件的使用
DirectShow 架構的優點 元件化,可重用性高 各種用途的元件,都化身為標準的 Filter ,具備相同的介面,容易搭接各式 Filter 極具彈性,透過對 Filter 的客製及組裝,可以達成各式的目的
DirectShow 核心元件 IFilterGraph 每個撥放結構都是用一個 IFilterGraph 所描述 IGraphBuilder 建立 、 控制 IFilterGraph 的元件 IBaseFilter DirectShow 中所有的 Filter 都實作的介面 IPin 代表多媒體訊息在 IFilterGraph 中流動的接腳 每個 IBaseFilter 都有一個以上的 IPin IMediaControl 控制多媒體訊息撥放行為的元件 IMediaEvent 取得多媒體訊息撥放時的事件
一個最簡單的 DirectShow 範例 ( DSFilePlayer.cpp) 目的:從檔案執行撥放指定的多媒體檔案 步驟: 初始化 COM 建立 IFilterGraph 的 instance 取得 IMediaControl 的介面( IFilterGraph 實作了 IMediaControl 的介面) 取得 IMediaEvent  ( IFilterGraph 實作了 IMediaEvent 的介面) 透過 IMediaControl 智慧型的建立 Filter Graph 的內容 透過 IMediaControl 啟動撥放 透過 IMediaEvent 等待撥放結束
初始化 COM HRESULT hr; hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); if( FAILED(hr) ) { CoUninitialize(); return hr; }
建立 IFilterGraph 的 instance IFilterGraph *pFilterGraph = NULL; // hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,IID_IFilterGraph, (void**) &pFilterGraph);
取得 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; }
建立 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); } } }
何謂 Filter Graph ? *Render WMV9 時會自動建立的 Filter Graph *Render MPEG 時會自動建立的 Filter Graph Output Pin Input Pin 分流 Renderer Source Filter Splitter
何謂 Filter ? 一個 Filter 具備一個以上的 Pin Pin 依多媒體訊息流動的方向可分為 Input Pin 或 Output Pin Filter 的 Input Pin ,代表對此 Filter 是訊息流入的 Pin Filter 的 Outut Pin ,代表對此 Filter 是訊息流出的 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 相符
Filter Graph 的建立 智慧型連接需要的 Filter 手動建立 自己產生所需的各種 Filter 依據需求把要連接在一起的兩兩 Filter 接在一起 把 Filter A 的 Output Pin 接到 Filter B 的 Input Pin
如何開始 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 用)
如何設定 DirectShow 應用程式的專案 在專案設定中設定 C/C++ 及 Linker 的選項 C/C++ General Additional Include Directories ,加上: BaseClasses\ Preprocessor Preprocessor Definitions ,加上: _WIN32_DCOM Linker General Additional Library Directories ,加上:  BaseClasses\Debug 或 BaseClasses\Release (視 debug mode 或 release 而定,加上這兩個目錄的原因是要將 Input 中指定的 strmbasd.lib 或 strmbase.lib 加入) Input Additional Dependencies ,加上: strmbasd.lib (或 strmbase.lib ,視 debug mode 或 release 而定)  winmm.lib
BaseClasses 及 DirectShow 範例 雖然  BaseClasses 被放在 DirectShow 的範例程式中,但其實提供了對於 DirectShow COM 介面的高階實作 基於 BaseClasses ,繼承其類別,對於實作 DirectShow 中的各式 Filter 有相當大的幫助 在撰寫各式 Filter 時,建議參考 DirectShow 中的範例程式 例: DirectX 9.0 DXSDK\Samples\C++\DirectShow\Filters
範例程式中示範的基本 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
範例程式中示範的基本 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
多媒體呈現應用時常用到的 Push Source Filter QPushSource 是一個通用的範例 參考 QPushSource.cpp, QPushSource.h, QPushSourceGuids.h 繼承後覆寫,或直接改寫 QPushSourceStream 的 HRESULT GetMediaType(CMediaType *pMediaType) HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pRequest) 改寫 CLSID_QPushSource
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;
HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pRequest) Push Source Filter 的下游 Filter 會呼叫 DecideBufferSize() 來得知究竟應該準備多大的 buffer 空間來接收 Push Source Filter 傳入的資料 例如,對 640x480 的 RGB32 資料來說: pRequest->cbBuffer = 640*480*4;
如何使用 QPushSource 產生 QPushSource 的 instance pPushSource = (QPushSource*) QPushSource::CreateInstance(NULL, &hr); 由 QPushSource 的 Output Pin 開始 Render FilterGraph
使用 QPushSource 的步驟 設定或繼承並覆寫 QPushSourceStream::GetMediaType 指定正確的 Media Type 及 Format 設定或繼承並覆寫 QPushSourceStream::DecideBufferSize 指定足夠大的 buffer 大小 修改範例 main.cpp 中的 HowToAddANewFrame() ,把多媒體訊息加入至 QPushSource 中的 queue
main.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);
Q&A Thanks

More Related Content

PDF
系統程式 -- 第 5 章
鍾誠 陳鍾誠
 
PDF
系統程式 -- 第 8 章
鍾誠 陳鍾誠
 
PDF
系統程式 -- 第 7 章
鍾誠 陳鍾誠
 
PDF
系統程式 -- 第 4 章
鍾誠 陳鍾誠
 
PDF
Hello world 的一生
Wen Liao
 
PDF
系統程式 -- 第 12 章
鍾誠 陳鍾誠
 
PDF
用Cython封装c++代码为python模块的一点经验
Leo Zhou
 
PPTX
Hcsm lect-20120913
lusecheng
 
系統程式 -- 第 5 章
鍾誠 陳鍾誠
 
系統程式 -- 第 8 章
鍾誠 陳鍾誠
 
系統程式 -- 第 7 章
鍾誠 陳鍾誠
 
系統程式 -- 第 4 章
鍾誠 陳鍾誠
 
Hello world 的一生
Wen Liao
 
系統程式 -- 第 12 章
鍾誠 陳鍾誠
 
用Cython封装c++代码为python模块的一点经验
Leo Zhou
 
Hcsm lect-20120913
lusecheng
 

What's hot (19)

PDF
系統程式 -- 第 11 章
鍾誠 陳鍾誠
 
DOCX
系統程式 -- 第 1 章 系統軟體
鍾誠 陳鍾誠
 
PDF
COSCUP 2016 - LLVM 由淺入淺
宗凡 楊
 
PDF
系統程式 - 附錄
鍾誠 陳鍾誠
 
DOCX
系統程式 -- 第 7 章 高階語言
鍾誠 陳鍾誠
 
PDF
Coscup2011: porting android to brand-new cpu architecture
lusecheng
 
DOCX
系統程式 -- 附錄
鍾誠 陳鍾誠
 
PDF
系統程式 -- 第 3 章
鍾誠 陳鍾誠
 
PDF
少年科技人雜誌 2015 年八月
鍾誠 陳鍾誠
 
DOCX
系統程式 -- 第 3 章 組合語言
鍾誠 陳鍾誠
 
PDF
COSCUP 2014 : open source compiler 戰國時代的軍備競賽
Kito Cheng
 
PDF
系統程式 -- 第 6 章
鍾誠 陳鍾誠
 
DOCX
系統程式 -- 第 5 章 連結與載入
鍾誠 陳鍾誠
 
PDF
icecream / icecc:分散式編譯系統簡介
Kito Cheng
 
PDF
LLVM introduction
National Cheng Kung University
 
PPTX
認識 C++11 新標準及使用 AMP 函式庫作平行運算
建興 王
 
PDF
系統程式 -- 第 9 章
鍾誠 陳鍾誠
 
PPTX
Golangintro
理 傅
 
PDF
系統程式 -- 第 10 章
鍾誠 陳鍾誠
 
系統程式 -- 第 11 章
鍾誠 陳鍾誠
 
系統程式 -- 第 1 章 系統軟體
鍾誠 陳鍾誠
 
COSCUP 2016 - LLVM 由淺入淺
宗凡 楊
 
系統程式 - 附錄
鍾誠 陳鍾誠
 
系統程式 -- 第 7 章 高階語言
鍾誠 陳鍾誠
 
Coscup2011: porting android to brand-new cpu architecture
lusecheng
 
系統程式 -- 附錄
鍾誠 陳鍾誠
 
系統程式 -- 第 3 章
鍾誠 陳鍾誠
 
少年科技人雜誌 2015 年八月
鍾誠 陳鍾誠
 
系統程式 -- 第 3 章 組合語言
鍾誠 陳鍾誠
 
COSCUP 2014 : open source compiler 戰國時代的軍備競賽
Kito Cheng
 
系統程式 -- 第 6 章
鍾誠 陳鍾誠
 
系統程式 -- 第 5 章 連結與載入
鍾誠 陳鍾誠
 
icecream / icecc:分散式編譯系統簡介
Kito Cheng
 
認識 C++11 新標準及使用 AMP 函式庫作平行運算
建興 王
 
系統程式 -- 第 9 章
鍾誠 陳鍾誠
 
Golangintro
理 傅
 
系統程式 -- 第 10 章
鍾誠 陳鍾誠
 
Ad

Introduction To Direct Show

  • 1. Introduction to DirectShow Qing [email protected] (Email/MSN) 2007/1/12
  • 2. 何謂 DirectShow ? DirectShow 是 DirectX 家族中的一支 除了 DirectShow 之外, DirectShow 尚包括了 DirectPlay DirectDraw Direct3D DirectMusic DirectShow 的用途在於多媒體資訊的呈現 視訊 音訊
  • 3. DirectShow 的應用範圍 多媒體訊息的輸入 麥克風 攝影機 檔案 網路串流 多媒體訊息的剖析 多媒體訊息的編碼,解碼 多媒體訊息的撥放 音訊視訊呈現 多媒體訊息的儲存
  • 4. 使用 DirectShow 必備 C/C++/VB/C# Windows COM 元件的使用
  • 5. DirectShow 架構的優點 元件化,可重用性高 各種用途的元件,都化身為標準的 Filter ,具備相同的介面,容易搭接各式 Filter 極具彈性,透過對 Filter 的客製及組裝,可以達成各式的目的
  • 6. DirectShow 核心元件 IFilterGraph 每個撥放結構都是用一個 IFilterGraph 所描述 IGraphBuilder 建立 、 控制 IFilterGraph 的元件 IBaseFilter DirectShow 中所有的 Filter 都實作的介面 IPin 代表多媒體訊息在 IFilterGraph 中流動的接腳 每個 IBaseFilter 都有一個以上的 IPin IMediaControl 控制多媒體訊息撥放行為的元件 IMediaEvent 取得多媒體訊息撥放時的事件
  • 7. 一個最簡單的 DirectShow 範例 ( DSFilePlayer.cpp) 目的:從檔案執行撥放指定的多媒體檔案 步驟: 初始化 COM 建立 IFilterGraph 的 instance 取得 IMediaControl 的介面( IFilterGraph 實作了 IMediaControl 的介面) 取得 IMediaEvent ( IFilterGraph 實作了 IMediaEvent 的介面) 透過 IMediaControl 智慧型的建立 Filter Graph 的內容 透過 IMediaControl 啟動撥放 透過 IMediaEvent 等待撥放結束
  • 8. 初始化 COM HRESULT hr; hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); if( FAILED(hr) ) { CoUninitialize(); return hr; }
  • 9. 建立 IFilterGraph 的 instance IFilterGraph *pFilterGraph = NULL; // hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,IID_IFilterGraph, (void**) &pFilterGraph);
  • 10. 取得 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; }
  • 11. 建立 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); } } }
  • 12. 何謂 Filter Graph ? *Render WMV9 時會自動建立的 Filter Graph *Render MPEG 時會自動建立的 Filter Graph Output Pin Input Pin 分流 Renderer Source Filter Splitter
  • 13. 何謂 Filter ? 一個 Filter 具備一個以上的 Pin Pin 依多媒體訊息流動的方向可分為 Input Pin 或 Output Pin Filter 的 Input Pin ,代表對此 Filter 是訊息流入的 Pin Filter 的 Outut Pin ,代表對此 Filter 是訊息流出的 Pin
  • 14. 何謂 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 相符
  • 15. Filter Graph 的建立 智慧型連接需要的 Filter 手動建立 自己產生所需的各種 Filter 依據需求把要連接在一起的兩兩 Filter 接在一起 把 Filter A 的 Output Pin 接到 Filter B 的 Input Pin
  • 16. 如何開始 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 用)
  • 17. 如何設定 DirectShow 應用程式的專案 在專案設定中設定 C/C++ 及 Linker 的選項 C/C++ General Additional Include Directories ,加上: BaseClasses\ Preprocessor Preprocessor Definitions ,加上: _WIN32_DCOM Linker General Additional Library Directories ,加上: BaseClasses\Debug 或 BaseClasses\Release (視 debug mode 或 release 而定,加上這兩個目錄的原因是要將 Input 中指定的 strmbasd.lib 或 strmbase.lib 加入) Input Additional Dependencies ,加上: strmbasd.lib (或 strmbase.lib ,視 debug mode 或 release 而定) winmm.lib
  • 18. BaseClasses 及 DirectShow 範例 雖然 BaseClasses 被放在 DirectShow 的範例程式中,但其實提供了對於 DirectShow COM 介面的高階實作 基於 BaseClasses ,繼承其類別,對於實作 DirectShow 中的各式 Filter 有相當大的幫助 在撰寫各式 Filter 時,建議參考 DirectShow 中的範例程式 例: DirectX 9.0 DXSDK\Samples\C++\DirectShow\Filters
  • 19. 範例程式中示範的基本 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
  • 20. 範例程式中示範的基本 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
  • 21. 多媒體呈現應用時常用到的 Push Source Filter QPushSource 是一個通用的範例 參考 QPushSource.cpp, QPushSource.h, QPushSourceGuids.h 繼承後覆寫,或直接改寫 QPushSourceStream 的 HRESULT GetMediaType(CMediaType *pMediaType) HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pRequest) 改寫 CLSID_QPushSource
  • 22. 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;
  • 23. HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pRequest) Push Source Filter 的下游 Filter 會呼叫 DecideBufferSize() 來得知究竟應該準備多大的 buffer 空間來接收 Push Source Filter 傳入的資料 例如,對 640x480 的 RGB32 資料來說: pRequest->cbBuffer = 640*480*4;
  • 24. 如何使用 QPushSource 產生 QPushSource 的 instance pPushSource = (QPushSource*) QPushSource::CreateInstance(NULL, &hr); 由 QPushSource 的 Output Pin 開始 Render FilterGraph
  • 25. 使用 QPushSource 的步驟 設定或繼承並覆寫 QPushSourceStream::GetMediaType 指定正確的 Media Type 及 Format 設定或繼承並覆寫 QPushSourceStream::DecideBufferSize 指定足夠大的 buffer 大小 修改範例 main.cpp 中的 HowToAddANewFrame() ,把多媒體訊息加入至 QPushSource 中的 queue
  • 26. main.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);