為何選擇 DirectShow
隨著網路普及,串流媒體應用爆發式增長。DirectShow 作為微軟 Windows 平台官方串流媒體開發套件 (隨 DirectX 發布,最新 8.1),提供強大的捕捉、回放、格式支援 (ASF、MPEG、AVI、DV、MP3、WAV)、DVD 播放、非線性編輯、DV 裝置交換,且具開放架構可自訂元件。
核心架構:Filter Graph 模型
DirectShow 以 Filter Graph 管理資料流處理流程。功能模組稱 Filter,依序連接成「流水線」:
- Source Filters:取得資料 (檔案、網路、採集卡、DV 機)
- Transform Filters:格式轉換、解碼、色彩空間轉換、取樣率轉換
- Rendering Filters:最終輸出 (聲卡、顯卡播放、檔案存儲)
每類通常包含多個 Filter 協同工作。應用程式透過 Filter Graph Manager 建立與控制 Graph,接收事件訊息實現互動。
開發利器:GraphEdit
SDK 內建 GraphEdit.exe (路徑 DXSDK\bin\DXUtils\) 可視化建構/測試 Filter Graph。快速體驗:開啟媒體檔 → 自動建構 Graph → 點擊播放 → 即得一個播放器原型。
Filter 開發核心三大議題
- Pin 連接協商:輸出 Pin 向輸入 Pin 列舉媒體類型,雙向協商找到共同支援格式。參考
amfilter.cpp 中 CBasePin::Connect。
- 資料傳輸模式:
- 推模式:Source Filter 主動產生資料,獨立執行緒透過
IMemInputPin::Receive 推送 (如 WDM 採集卡)。
- 拉模式:Source Filter 被動,下游 Parser/Splitter 執行緒透過
IAsyncReader::Request/SyncRead 拉取 (如檔案源)。
資料以 Sample (COM 物件) 封裝,由 Allocator 管理記憶體,連接的 Pin 共享 Allocator 避免記憶體複製。
- 媒體定位:透過
IMediaSeeking 實現隨機存取。Graph Manager 從 Renderer 向上查詢支援該介面的 Pin (通常在 Source/Parser),取得總長度、目前位置。開發者需在適當 Pin 實現或轉發 QueryInterface。
手把手教你寫 Filter
專案建立要點
- VC++ 建立 Win32 Dynamic-Link Library,輸出副檔名改為
.ax。
- 必備
.def 定義四個匯出函式、DllRegisterServer/DllUnregisterServer 註冊 Filter。
- 使用
GuidGen.exe 產生唯一 GUID。
基類選擇策略
| Filter 類型 | 建議基類 | 適用情境 |
| Source | CSource | 資料產生端 (採集卡、檔案讀取) |
| Transform (一進一出、媒體型同) | CTransInPlaceFilter | 就地處理 (亮度調整、水印) |
| Transform (媒體型轉換) | CTransformFilter | 解碼器、色彩空間轉換 |
| Renderer | CBaseRenderer / CBaseVideoRenderer | 音訊/視訊輸出 |
原則:功能單一化、明確 Pin 數量與媒體型、特殊需求 (非一對一 Sample、需緩衝執行緒) 可考慮繼承 CSource 實作自訂邏輯。
關鍵實作重點
- Input Pin:實作
CheckMediaType、Receive (推模式)、EndOfStream/BeginFlush/EndFlush。
- Output Pin:實作
CheckMediaType、DecideBufferSize、GetMediaType。
- Filter 類別:實作
CreateInstance (COM 入口)、NonDelegatingQueryInterface (暴露介面)、GetPinCount/GetPin (自訂 Pin)。
- 邏輯程式碼與 Filter 架構程式碼分離,利於維護。
避坑指南:五大常見陷阱
- 雙重鎖死結:Filter 物件鎖 (狀態轉換) 與資料流鎖 (
Receive) 混淆易死結。
- EndOfStream 處理:收到後不可再理會新資料;若有緩衝必須處理完畢才返回。
- Media Seeking 協作:轉發 QueryInterface;緩衝型 Filter 需重載
BeginFlush/EndFlush/NewSegment;時間戳重算。
- 專用執行緒安全:避免死迴圈,定期檢查執行緒命令,確保 Graph 關閉時執行緒正常結束。
- 媒體型資訊取得時機:在
CompleteConnect 而非 SetMediaType 取得影像寬高等格式資訊。
DirectX Media Objects (DMO):輕量級替代方案
DMO 為微軟推薦的編解碼器開發模式 (DirectX 9 獨立於 DirectShow)。優點:結構簡單、同步處理免多執行緒、應用程式直接呼叫不需 Graph、記憶體由呼叫端管理、支援多輸入/輸出。核心流程:設定媒體型 → 分配緩衝 (IMediaBuffer) → ProcessInput/ProcessOutput (或 In-Place Process) → Discontinuity/Flush。可透過 DMO Wrapper Filter 在 DirectShow 中使用。
- 上一篇文章: VC++ 實作 GPS 定位資料解析:從串口接收到座標提取完整流程
- 下一篇文章: WTL 自繪按鈕實作全解析:結合 COwnerDraw 與 CBitmapButtonImpl
Copyright ©
程式碼之家 All Rights Reserved