示例深度解析:基于 Media Foundation 的視頻特效處理與 UWP 設(shè)備應(yīng)用集成)
示例工程【免費下載鏈接】Windows-driver-samplesThis repo contains driver samples prepared for use with Microsoft Visual Studio and the Windows Driver Kit (WDK). It contains both Universal Windows Driver and desktop-only driver samples.項目地址https://gitcode.com/gh_mirrors/wi/Windows-driver-samples點擊查看免費下載導(dǎo)讀本文以 avstream/samplemft0 為例系統(tǒng)講解 Windows 驅(qū)動開發(fā)者如何實現(xiàn)一個Driver MFT又稱 MFT0——即攝像頭視頻捕獲管線中第一個被應(yīng)用的 Media Foundation Transform。讀完本文你將掌握 MFT0 的概念定位、面向 UWP 設(shè)備應(yīng)用的控制接口設(shè)計、IMFTransform 全接口實現(xiàn)套路、視頻幀逐行處理原理以及如何將 MFT0 隨驅(qū)動包分發(fā)并用于實現(xiàn)實時視頻特效。一、什么是 Driver MFTMFT0在 Windows 10 及以上的攝像頭驅(qū)動架構(gòu)中當(dāng)應(yīng)用通過 Media FoundationMF從攝像頭捕獲視頻時視頻流會經(jīng)過一串變換Transform。Driver MFT 是這一串變換中第一個被應(yīng)用到攝像頭視頻流的 MFT因此也常被稱為MFT0。它在設(shè)備驅(qū)動側(cè)運行隨攝像頭驅(qū)動包一起分發(fā)屬于“驅(qū)動擴展”而非純應(yīng)用層組件它可以在從攝像頭捕獲照片或視頻時提供視頻特效或其他圖像處理并且無需修改驅(qū)動本身它的啟用、參數(shù)調(diào)節(jié)可以交由配套的UWP 設(shè)備應(yīng)用UWP device app來控制。在 README 中官方給出的定位描述是“A driver MFT is a Media Foundation Transform thats used with a specific camera when capturing video … It can be distributed along with the driver package for a camera.”也就是說MFT0 是與某個特定攝像頭綁定的它只在系統(tǒng)識別到該攝像頭并開始捕獲時才被加載。二、示例效果綠色/純色框替換視頻局部本示例的演示效果非常直觀當(dāng) MFT0 被啟用時它會把捕獲視頻的一部分替換為一個純色框README 描述為 green box。剩余畫面原樣透傳從而證明MFT0 已成功掛接到攝像頭捕獲管線MFT0 有能力對每一幀視頻數(shù)據(jù)做實際的像素級改寫特效的開啟與范圍可以由外部UWP 設(shè)備應(yīng)用動態(tài)控制。從源碼看這一效果在CMft0::OnProcessOutput中實現(xiàn)Mft0.cpp輸入幀與輸出幀分別被鎖定后按行復(fù)制像素凡位于lines閾值之下的行即畫面底部區(qū)域用memset填零形成一個純色塊其余行memcpy原樣拷貝。lines由成員變量m_percentOfScreen默認(rèn) 50即畫面 50%計算long lines uiHeight; if(m_percentOfScreen ! -1 m_percentOfScreen ! 0) { lines (UINT)(uiHeight * (1.0 - m_percentOfScreen / 100.00)); }注意當(dāng)m_percentOfScreen為-1或0時lines uiHeight整幀被完整透傳相當(dāng)于特效關(guān)閉因此 UWP 設(shè)備應(yīng)用可以通過把該值設(shè)為 0 來“消除”遮擋??虻摹邦伾睂?yīng)零值填充數(shù)據(jù)開發(fā)者可自行替換為任意 RGB 填充邏輯以實現(xiàn)真正的綠色或其他顏色框。三、運行與測試的前提條件README 明確列出要真正運行本示例需要以下配套條件缺一不可前提說明配套 UWP 設(shè)備應(yīng)用Device app for camera sample提供 UWP 設(shè)備應(yīng)用用于控制 Driver MFT 實現(xiàn)的特效即調(diào)用本文第五節(jié)介紹的 IMft0 控制接口攝像頭捕獲 UI 示例Camera Capture UI sample提供一種方式去調(diào)用上述 UWP 設(shè)備應(yīng)用從而在真實拍攝界面里看到特效開關(guān)效果特定攝像頭的設(shè)備 ID本示例“綁定”特定相機運行時需要相機的設(shè)備 ID 才能把 MFT0 關(guān)聯(lián)到該設(shè)備設(shè)備元數(shù)據(jù)包device metadata package用于把 UWP 設(shè)備應(yīng)用與特定攝像頭關(guān)聯(lián)起來是設(shè)備應(yīng)用被系統(tǒng)按設(shè)備調(diào)用的關(guān)鍵也就是說MFT0 本身無法獨立演示——它必須與 UWP 設(shè)備應(yīng)用、捕獲 UI 以及一臺具體攝像頭或?qū)?yīng)的模擬環(huán)境組成完整鏈路。構(gòu)建與部署時還需將生成的 DLL 放進相機的驅(qū)動包見下文打包章節(jié)。四、工程結(jié)構(gòu)與構(gòu)建方式4.1 文件清單avstream/samplemft0/目錄下各文件職責(zé)如下文件職責(zé)Mft0.cpp / Mft0.hCMft0類的全部實現(xiàn)IMFTransform 各方法、IMft0 控制方法、圖像處理核心SampleMft0.idlMIDL 接口定義聲明IMft0控制接口與Mft0coclass、類型庫 GUIDSampleMft0.cppDLL 導(dǎo)出入口DllCanUnloadNow、DllGetClassObject、DllRegisterServer等SampleMft0.def模塊導(dǎo)出表聲明上述 5 個 DLL 導(dǎo)出函數(shù)SampleMft0.rgs / Mft0.rgsATL 注冊腳本寫入 COM CLSID、InprocServer32、ThreadingModel 等注冊表項dllmain.cpp / dllmain.hDllMain與 ATL 模塊類CSampleMft0ModuleSampleHelpers.h公共輔助錯誤檢查宏、VideoBufferLock緩沖鎖定工具類SampleMft0.vcxproj主工程產(chǎn)出SampleMft0.dllPackage/package.vcxproj打包工程產(chǎn)出驅(qū)動安裝包SampleMft0.sln解決方案包含上述兩個工程4.2 構(gòu)建配置要點從 SampleMft0.vcxproj 可以看到使用 WDK 的WindowsApplicationForDrivers10.0工具集ConfigurationType為DynamicLibrary生成 DLL支持x64 與 ARM64兩種平臺Debug/Release 均以Windows 10為目標(biāo)版本輸出目標(biāo)名TargetName為SampleMft0即最終產(chǎn)物為SampleMft0.dll。Package/package.vcxproj 則以WindowsKernelModeDriver10.0工具集、DriverType為Package的 Utility 工程形式將生成的 DLL 與驅(qū)動包元數(shù)據(jù)一起封裝便于隨相機驅(qū)動包分發(fā)。這正對應(yīng) README 中“driver MFT 可以隨相機驅(qū)動包一起分發(fā)”的定位。五、核心源碼剖析5.1 COM 對象模型一個類三重身份CMft0Mft0.h基于 ATL 實現(xiàn)同時實現(xiàn)三個接口class ATL_NO_VTABLE CMft0 : public CComObjectRootExCComMultiThreadModel, public CComCoClassCMft0, CLSID_Mft0, public IMft0, // 面向 UWP 設(shè)備應(yīng)用的控制接口 public IMFTransform, // Media Foundation Transform 核心接口 public IInspectable // WinRT 可檢查性接口IMFTransform讓對象成為標(biāo)準(zhǔn) MFT被媒體管線按 Transform 協(xié)議調(diào)用IMft0示例自定義的控制接口供 UWP 設(shè)備應(yīng)用調(diào)用見 5.2IInspectable使對象可作為 WinRT 對象被元數(shù)據(jù)檢查GetIids、GetRuntimeClassName、GetTrustLevel其中信任級別返回BaseTrust見 Mft0.cpp。構(gòu)造函數(shù)初始化了關(guān)鍵狀態(tài)m_bEnableEffects TRUE、m_percentOfScreen 50并創(chuàng)建臨界區(qū)m_critSec保護所有狀態(tài)所有核心方法都通過EnterCriticalSection/LeaveCriticalSection保證線程安全。5.2 控制接口 IMft0UWP 設(shè)備應(yīng)用如何遙控特效SampleMft0.idl 定義了四個方法其語義與實現(xiàn)Mft0.cpp一一對應(yīng)interface IMft0 : IUnknown{ [id(1)] HRESULT UpdateDsp([in] UINT32 uiPercentOfScreen); [id(2)] HRESULT Enable(void); [id(3)] HRESULT Disable(void); [id(4)] HRESULT GetDspSetting([out] UINT* puiPercentOfScreen, [out] BOOL* pIsEnabled); };方法作用實現(xiàn)要點UpdateDsp(uiPercentOfScreen)設(shè)置特效覆蓋屏幕的比例0~1000 或 -1 表示全透傳直接寫入m_percentOfScreenEnable()開啟特效置m_bEnableEffects TRUEDisable()關(guān)閉特效置m_bEnableEffects FALSEGetDspSetting(...)查詢當(dāng)前比例與開關(guān)狀態(tài)同時回讀m_percentOfScreen與m_bEnableEffects這就是 README 所說“UWP 設(shè)備應(yīng)用控制 Driver MFT 實現(xiàn)的特效”的底層通道設(shè)備應(yīng)用拿到 MFT0 對象后通過這 4 個方法即可實時調(diào)整畫面中色塊的大小和開關(guān)無需重啟捕獲會話。5.3 流模型固定 1 進 1 出CMft0是一個最簡單的單進單出 MFTGetStreamLimits返回輸入/輸出均為最小 1、最大 1Mft0.cppGetStreamCount同樣返回 1 進 1 出GetStreamIDs直接返回E_NOTIMPL表示流 ID 固定為 0按 MFT 協(xié)議單流 MFT 可省略流 IDIsValidInputStream/IsValidOutputStream均只接受dwInputStreamID 0。輸入流信息聲明了MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER輸出流聲明了MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_PROVIDES_SAMPLES | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE——即每個樣本攜帶一整幀且 MFT 自行提供輸出樣本見 GetInputStreamInfo 與 GetOutputStreamInfo。5.4 與底層相機源的綁定MFT0 之所以能拿到“這個攝像頭支持的媒體類型”關(guān)鍵在于它通過輸入流屬性反向找到底層相機源從輸入屬性中讀取MFT_CONNECTED_STREAM_ATTRIBUTEMft0.cpp再從該屬性中取出MF_DEVICESTREAM_EXTENSION_PLUGIN_CONNECTION_POINTQueryInterface得到IMFTransform類型的m_pSourceTransform——即相機的源變換讀取MF_DEVICESTREAM_STREAM_CATEGORY判斷流類型代碼打印PINNAME_VIDEO_CAPTURE/PINNAME_VIDEO_PREVIEW/PINNAME_VIDEO_STILL/PINNAME_IMAGE并且只接受PINNAME_VIDEO_PREVIEW或PINNAME_VIDEO_CAPTURE其他類型返回E_UNEXPECTED調(diào)用GenerateMFMediaTypeListFromDeviceMft0.cpp遍歷源變換的所有GetOutputAvailableType篩出可處理的視頻格式后存入m_listOfMediaTypes。GetInputAvailableType/GetOutputAvailableType之后都從m_listOfMediaTypes返回候選媒體類型GetMediaTypeMft0.cpp。SetInputType則通過IsMediaTypeSupported校驗支持MFT_SET_TYPE_TEST_ONLY試設(shè)模式并把完整媒體類型同時緩存為輸入/輸出類型。5.5 數(shù)據(jù)流ProcessInput → ProcessOutput處理流程是 MFT 的教科書式實現(xiàn)ProcessInputMft0.cpp校驗流 ID、校驗類型已設(shè)置否則MF_E_NOTACCEPTING、校驗緩沖數(shù)0 個返回E_FAIL多于 1 個返回MF_E_SAMPLE_HAS_TOO_MANY_BUFFERS然后緩存輸入樣本m_pSample并 AddRefGetInputStatus / GetOutputStatusMft0.cpp以m_pSample是否為 NULL 作為是否可接受輸入/是否有輸出就緒的唯一判據(jù)ProcessOutputMft0.cpp無緩存樣本時返回MF_E_TRANSFORM_NEED_MORE_INPUT否則創(chuàng)建輸出樣本、把輸入/輸出緩沖轉(zhuǎn)成連續(xù)緩沖調(diào)用OnProcessOutput做像素處理并將輸入樣本的時間戳與時長拷貝到輸出樣本后釋放輸入樣本ProcessMessageMft0.cppMFT_MESSAGE_COMMAND_FLUSH觸發(fā)OnFlush釋放緩存樣本MFT_MESSAGE_COMMAND_DRAIN無需額外動作MFT_MESSAGE_SET_D3D_MANAGER返回E_NOTIMPL未聲明 D3D 感知。5.6 像素級處理幀格式、stride 與 VideoBufferLockOnProcessOutput只在m_bEnableEffects為 TRUE 且子類型屬于受支持的 29 種視頻格式時才做處理格式清單涵蓋RGB 系RGB8、RGB555、RGB565、RGB24、RGB32、ARGB32、AI44YUV 平面/半平面I420、IYUV、NV11、NV12、YV12、P010、P016、P210、P216YUV 打包/交織AYUV、UYVY、Y41P、Y41T、Y42T、YUY2、v210、v216、v410、Y210、Y216、Y410、Y416。完整條件見 Mft0.cpp 與 GenerateMFMediaTypeListFromDevice。行步長stride的處理是本例最值得借鑒的部分GetDefaultStrideMft0.cpp優(yōu)先讀取MF_MT_DEFAULT_STRIDE未設(shè)置時用MFGetStrideForBitmapInfoHeader按子類型與寬度計算并回寫屬性緩存SampleHelpers.h 中的VideoBufferLock封裝了緩沖鎖定優(yōu)先QueryInterface到IMF2DBuffer走Lock2D否則走IMFMediaBuffer::Lock并處理bottom-up負 stride返回內(nèi)存中最后一行即圖像頂行與 top-down 兩種布局OnProcessOutput按行memcpy上半部分、memset下半部分同時正確處理負 stride 場景Mft0.cpp。這一套“默認(rèn) stride 計算 2D 緩沖回退 方向處理”的模式是編寫任何逐像素 MFT 的通用基礎(chǔ)設(shè)施。5.7 全局屬性異步關(guān)閉、動態(tài)格式更改與硬件 URLGetAttributesMft0.cpp創(chuàng)建并返回三個關(guān)鍵屬性屬性值含義MF_TRANSFORM_ASYNCFALSEMFT 為同步處理模式管線按傳統(tǒng) ProcessInput/ProcessOutput 輪詢MFT_ENUM_HARDWARE_URL_AttributeLSample_CameraExtensionMft硬件 MFT 枚舉 URL供系統(tǒng)按名稱識別/枚舉該擴展 MFTMFT_SUPPORT_DYNAMIC_FORMAT_CHANGETRUE支持動態(tài)格式更改配合SetInputType的校驗邏輯輸入流屬性同樣攜帶MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE與相同的硬件 URLMft0.cpp。需要說明的是雖然示例在全局/輸入屬性中聲明支持動態(tài)格式更改SetOutputType只是轉(zhuǎn)發(fā)到SetInputType且DeleteInputStream/AddInputStreams均返回E_NOTIMPL——流數(shù)量固定不允許動態(tài)增刪。六、COM 注冊與驅(qū)動打包Mft0.rgs 注冊CLSID {7BB640D9-33A4-4759-B290-F41A31DCF848}Mft0 ClassInprocServer32指向%MODULE%ThreadingModel為Both并關(guān)聯(lián)類型庫{DE05674A-C564-4C0E-9B7C-E1519F7AA767}SampleMft0Libv1.0類型庫與 coclass 定義見 SampleMft0.idlOBJECT_ENTRY_AUTOMft0.h讓 ATL 在DllRegisterServer時自動寫入這些項SampleMft0.def 僅導(dǎo)出 5 個標(biāo)準(zhǔn) COM 入口DllRegisterServer/DllUnregisterServer/DllInstall實現(xiàn)在 SampleMft0.cpp。部署層面編譯出的SampleMft0.dll通過 Package 工程DriverTypePackage與相機驅(qū)動包一起封裝、簽名并分發(fā)——這正是 README 強調(diào)的“隨驅(qū)動包分發(fā)”能力。在實際驅(qū)動安裝時還需要在設(shè)備的驅(qū)動擴展配置inf 中引用 MFT0 CLSID/硬件 URL中聲明該 MFTMFT0 才會在該相機捕獲時被管線加載。七、測試鏈路與配套示例按照 README 的說明驗證本示例的完整鏈路為構(gòu)建SampleMft0.sln得到SampleMft0.dll并隨驅(qū)動包安裝到目標(biāo)相機部署Device app for camera sampleUWP 設(shè)備應(yīng)用它在拍攝界面里通過IMft0調(diào)用Enable/Disable/UpdateDsp/GetDspSetting實現(xiàn)對特效的實時控制運行Camera Capture UI sample它作為宿主捕獲界面調(diào)用 UWP 設(shè)備應(yīng)用讓用戶能直觀看到“畫面中一部分被色塊替換/恢復(fù)”的效果前提是擁有該相機的設(shè)備 ID與設(shè)備元數(shù)據(jù)包系統(tǒng)才會把 UWP 設(shè)備應(yīng)用與這臺相機、這個 MFT0 關(guān)聯(lián)起來。在調(diào)試階段代碼內(nèi)置了流類型打印wprintf(LStream type: PINNAME_VIDEO_CAPTURE\n)等與CHK_LOG_BRK錯誤宏SampleHelpers.h 輸出HR%08x File: %S Ln: %d配合調(diào)試器即可確認(rèn) MFT0 是否被正確掛接、媒體類型協(xié)商是否成功。八、相關(guān)主題與延伸閱讀攝像頭 UWP 設(shè)備應(yīng)用設(shè)計Device app for cameras本示例配套設(shè)備應(yīng)用的控制主體Media Foundation TransformsIMFTransform接口與 MFT 處理協(xié)議本文 5.3~5.5 節(jié)即其實戰(zhàn)實現(xiàn)Streaming media device driver design guide攝像頭驅(qū)動與流媒體設(shè)備驅(qū)動設(shè)計對應(yīng)本文 5.4 節(jié)“與底層源變換綁定”機制Universal camera driver design guideWindows 10 通用攝像頭驅(qū)動設(shè)計解釋了 MFT0 在通用相機驅(qū)動架構(gòu)中的掛載位置。如需深入可繼續(xù)閱讀本倉庫中avstream/samplemft0/目錄下的 Mft0.cpp、Mft0.h、SampleMft0.idl 與 SampleHelpers.h對照本文各節(jié)即可獲得完整的源碼級證據(jù)鏈。贊分享示例工程【免費下載鏈接】Windows-driver-samplesThis repo contains driver samples prepared for use with Microsoft Visual Studio and the Windows Driver Kit (WDK). It contains both Universal Windows Driver and desktop-only driver samples.項目地址https://gitcode.com/gh_mirrors/wi/Windows-driver-samples點擊查看免費下載相關(guān)推薦Stoic模型數(shù)據(jù)預(yù)處理如何準(zhǔn)備FASTA文件進行化學(xué)計量預(yù)測Stoic模型數(shù)據(jù)預(yù)處理如何準(zhǔn)備FASTA文件進行化學(xué)計量預(yù)測 Stoic模型HuggingFace鏡像/PickyBinders是一款強大的化學(xué)計量預(yù)測Obsidian美化終極指南從基礎(chǔ)到高級的完整個性化方案Obsidian美化終極指南從基礎(chǔ)到高級的完整個性化方案 Obsidian作為一款功能強大的Markdown筆記工具其核心魅力不僅在于強大的知識管理能力更文檔知識管理libusb攝像頭設(shè)備通信基于UVC協(xié)議的視頻流采集方案libusb攝像頭設(shè)備通信基于UVC協(xié)議的視頻流采集方案 引言突破USB攝像頭開發(fā)的底層難題 你是否曾在開發(fā)USB攝像頭應(yīng)用時遭遇這些困境調(diào)用系統(tǒng)API時驅(qū)動開發(fā)系統(tǒng)編程上一篇Zotero Style插件終極指南如何通過可視化界面提升文獻管理效率50%下一篇終極代碼助手Qwen2.5-Coder-1.5B-Instruct-GGUF的8大核心功能與實戰(zhàn)案例創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考