资讯动态

SimpleCapture:基于 Media Foundation 的摄像头视频预览示例(C++ 实战指南)

发布时间:2026/10/16 5:45:44 来源:尧图企业网站定制
示例工程【免费下载链接】Windows-classic-samplesThis repo contains samples that demonstrate the API used in Windows classic desktop applications.项目地址https://gitcode.com/gh_mirrors/wi/Windows-classic-samples点击查看免费下载导读SimpleCapture 是 Windows 经典桌面示例仓库中的一个 C 示例程序完整演示了如何使用Media FoundationMF从摄像头等视频采集设备获取实时预览画面。本文将围绕该示例的官方 README结合仓库中的 winmain.cpp 与 Preview.cpp 源码深入讲解设备枚举、MFPlay 播放管线搭建、窗口消息集成、设备热插拔设备丢失处理以及完整的构建运行流程。读完本文你将掌握一套可直接复用的选择摄像头并实时预览的 Win32 原生实现方案。示例概览示例解决什么问题SimpleCapture 的核心目标见 README.md是Demonstrates how to preview video from a capture device using Media Foundation.即使用 Media Foundation 预览来自采集设备的视频。它属于仓库Samples/Win7Samples/multimedia/mediafoundation/目录下的媒体基础示例之一与同目录的 MFCaptureToFile录制到文件形成互补前者解决看后者解决录。示例采用纯 C 实现基于MFPlayMFPlayer2API而非传统的拓扑Topology拼接方式。MFPlay 是 Media Foundation 提供的一个轻量级播放层应用只需与IMFPMediaPlayer接口交互由系统在内部完成 Source → EVR增强视频渲染器的管线编排极大简化了预览功能的代码量。工程结构与关键文件依据 README 的文件清单与 SimpleCapture.vcproj 中的项目配置示例由以下文件组成文件职责winmain.cppWin32 应用入口窗口过程、设备枚举、选择对话框、设备丢失通知Preview.cppCPreview预览封装类管理 MFPlay 播放器与媒体源Preview.hCPreview类的声明SimpleCapture.rc菜单File → Choose Device与设备选择对话框资源resource.h资源 ID 定义SimpleCapture.sln / SimpleCapture.vcproj解决方案与工程文件工程配置支持Win32 与 x64 两种平台Debug/Release 四种配置均链接mfplat.lib mf.lib mfplay.lib shlwapi.lib四个库见 SimpleCapture.vcproj其中mfplay.lib对应 MFPlay APIshlwapi.lib用于StrCmp等字符串辅助函数同时以WarnAsErrortrue将警告视为错误以确保代码质量。核心技术流程第一步枚举视频采集设备当用户在菜单栏选择File → Choose Device时OnChooseDevicewinmain.cpp会执行以下步骤用MFCreateAttributes创建属性存储并设置MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID声明只枚举视频采集设备调用MFEnumDeviceSources得到一组IMFActivate *指针数组每个指针代表一个摄像头设备通过DialogBoxParam弹出设备选择对话框资源IDD_CHOOSE_DEVICE定义于 SimpleCapture.rc用户在列表框中选定设备后将其IMFActivate指针交给CPreview::SetDevice启动预览。对话框初始化时OnInitDialog示例调用每个设备的GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, ...)获取设备友好名称如 USB Camera填充到列表框若设备数为 0则禁用OK按钮——这提供了一种无设备时的友好降级策略。第二步用 MFPlay 搭建预览管线CPreview::SetDevicePreview.cpp是预览启动的核心其调用序列为CloseDevice()释放上一次的播放器实例支持切换设备MFPCreateMediaPlayer(NULL, FALSE, 0, this, m_hwnd, m_pPlayer)创建播放器NULLURL 表示不使用文件地址而是稍后通过对象创建媒体项回调对象为this即CPreview自身它实现了IMFPMediaPlayerCallback视频渲染窗口句柄为m_hwndpActivate-ActivateObject(__uuidof(IMFMediaSource), ...)激活采集设备对应的IMFMediaSource媒体源通过pActivate-GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, ...)取得设备的符号链接symbolic link该字符串将用于后续设备丢失检测m_pPlayer-CreateMediaItemFromObject(pSource, FALSE, 0, NULL)以异步方式为媒体源创建媒体项。整个流程是异步驱动的CreateMediaItemFromObject完成后MFPlay 会通过回调通知OnMediaPlayerEvent触发MFP_EVENT_TYPE_MEDIAITEM_CREATED事件进而调用OnMediaItemCreated。第三步异步事件处理与自动窗口适配CPreview::OnMediaPlayerEventPreview.cpp是 MFPlay 事件的统一入口示例仅关心两类事件MFP_EVENT_TYPE_MEDIAITEM_CREATED媒体项创建完成。处理器OnMediaItemCreated先调用pMediaItem-HasVideo(bHasVideo, bIsSelected)判断媒体项是否含被选中的视频流再调用m_pPlayer-SetMediaItem(pMediaItem)将该媒体项设置为当前播放项MFP_EVENT_TYPE_MEDIAITEM_SET媒体项设置完成。处理器OnMediaItemSet调用m_pPlayer-GetNativeVideoSize(szVideo, NULL)取得视频的原始尺寸然后通过AdjustWindowRect与SetWindowPos将主窗口调整为恰好容纳该尺寸最后调用m_pPlayer-Play()开始播放预览。这段逻辑体现了 MFPlay 的一个重要特性预览窗口可以自动匹配采集视频的原始分辨率开发者无需关心具体摄像头是 640×480、720p 还是 1080p。第四步绘制与缩放WM_PAINT / WM_SIZE预览视频的画面渲染由 MFPlay 内部的 EVR 完成应用窗口只负责提供宿主句柄。在 winmain.cpp 中收到WM_PAINT时若g_pPreview-HasVideo()为真则调用CPreview::UpdateVideo()由播放器重绘当前帧否则用COLOR_APPWORKSPACE颜色填充背景收到WM_SIZE且状态为SIZE_RESTORED时同样调用UpdateVideo()让画面随窗口缩放。CPreview::UpdateVideo内部只是简单转发给m_pPlayer-UpdateVideo()窗口消息与 MFPlay 的对接由此完成。第五步设备丢失热插拔处理示例对摄像头被拔出这一真实场景做了完整处理这也是CPreview特意保存符号链接的原因应用启动创建窗口时OnCreate通过RegisterDeviceNotification注册DBT_DEVTYP_DEVICEINTERFACE类型、KSCATEGORY_CAPTURE类 GUID 的设备通知见 winmain.cpp系统在设备状态变化时向窗口发送WM_DEVICECHANGE窗口过程将其转交给OnDeviceLostOnDeviceLost调用CPreview::CheckDeviceLostPreview.cpp该方法将通知中的dbcc_name与保存的符号链接做不区分大小写的比较_wcsicmp若一致则判定当前预览设备已丢失一旦确认设备丢失OnDeviceLost调用CloseDevice()关闭采集源并弹出 Lost the capture device. 提示框。这一模式建议在任意接入摄像头、麦克风等采集设备的应用中复用。第六步资源释放CPreview::CloseDevicePreview.cpp集中完成清理对播放器调用m_pPlayer-Shutdown()并Release对媒体源调用m_pSource-Shutdown()并Release最后CoTaskMemFree释放符号链接缓冲。应用退出时CleanUp以及切换设备时都会调用该方法保证无 COM 资源泄漏。CPreview 类设计要点CPreviewPreview.h是一个典型的 COM 封装类继承IMFPMediaPlayerCallback实现IUnknown三方法QueryInterface使用QITAB/QISearch辅助宏与OnMediaPlayerEvent回调构造函数为private统一通过静态工厂方法CreateInstance(HWND hVideo, CPreview **ppPlayer)创建创建后引用计数为 1由调用方持有并在不再需要时Release对外暴露SetDevice / CloseDevice / UpdateVideo / CheckDeviceLost / HasVideo五个方法分别对应上文所述的核心操作接口划分清晰便于移植到其他 Win32 应用。构建与运行继承自官方 README使用命令行构建打开 Command Prompt进入示例目录即仓库中的Samples/Win7Samples/multimedia/mediafoundation/SimpleCapture执行命令msbuild SimpleCapture.sln该命令会按工程默认配置生成可执行文件Debug 或 Release取决于 msbuild 默认平台/配置。使用 Visual Studio 构建推荐在 Windows Explorer 中进入Samples/Win7Samples/multimedia/mediafoundation/SimpleCapture目录双击SimpleCapture.sln用 Visual Studio 打开解决方案在Build生成菜单中选择Build Solution生成解决方案应用将生成到默认的\Debug或\Release目录。运行示例通过命令提示符或 Windows Explorer 进入包含可执行文件的目录在命令行输入SimpleCapture.exe并回车或直接在 Windows Explorer 中双击SimpleCapture.exe图标。运行后从File → Choose Device菜单选择你的摄像头设备即可在自动调整好尺寸的窗口中看到实时视频预览拔出摄像头时程序会提示设备丢失并停止预览。从源码看实现细节与扩展思路依赖的 Windows 头文件从 winmain.cpp 的#include可以看到该示例涉及的核心 API 头文件mfapi.hMedia Foundation 基础 API含MFEnumDeviceSources、mfplay.hMFPlay 播放器 API、Dbt.h设备通知结构、ks.h/ksmedia.hKSCATEGORY_CAPTURE设备类别 GUID。构建时需确保目标系统具备 Windows 7 及以上的 Media Foundation 运行环境。与录制到文件示例的对比两条不同技术路线仓库中同目录的 MFCaptureToFile 示例 负责采集并写入文件其 capture.cpp 采用了完全不同的架构基于Source Reader Sink WriterMFCreateSourceReaderFromMediaSource/MFCreateSinkWriterFromURL通过IMFSourceReaderCallback::OnReadSample回调逐帧取出样本并WriteSample写入文件还会对时间戳做 rebasellTimeStamp - m_llBaseTime处理。两者对比可以得出清晰的选型结论只需要实时预览SimpleCapture 场景用 MFPlay代码量最小需要采集录像、逐帧处理或自定义管线用 Source Reader / Sink Writer 或自行构建拓扑。两个示例在设备枚举与设备丢失检测部分代码高度相似都使用MFEnumDeviceSources 符号链接比对说明这两段逻辑是 Media Foundation 采集类应用的通用范式可直接借鉴。常见问题与排错提示构建报缺少 mfplay.lib / mf.lib确认 SDK 版本支持 Media FoundationWindows 7 SDK 及以上并检查 SimpleCapture.vcproj 中的AdditionalDependencies是否完整。运行后设备列表为空 / OK 按钮置灰说明系统未检测到任何摄像头设备检查设备管理器中摄像头驱动是否正常、是否被其他应用独占占用。切换设备失败SetDevice开头会先CloseDevice()释放旧实例若仍异常请确认回调对象this的引用计数管理正确CPreview构造时引用计数为 1MFPCreateMediaPlayer不会额外持有它。拔出摄像头后程序无反应确认OnCreate中RegisterDeviceNotification已成功注册且注册类别为KSCATEGORY_CAPTURE设备通知回调依赖消息循环正常派发WM_DEVICECHANGE。小结SimpleCapture 以约 1000 行 C 代码展示了 Media Foundation 采集预览的完整闭环设备枚举MFEnumDeviceSources→ 媒体源激活IMFActivate→ MFPlay 异步播放IMFPMediaPlayer→ 窗口消息集成WM_PAINT/WM_SIZE→ 设备热插拔防护RegisterDeviceNotification 符号链接比对。其中CPreview封装类的职责划分、符号链接的保存策略以及设备丢失处理流程均可直接迁移到其他 Windows 原生桌面应用中。如需进一步掌握从采集到落盘的完整链路可继续阅读同仓库的 MFCaptureToFile 示例作对比学习。赞分享示例工程【免费下载链接】Windows-classic-samplesThis repo contains samples that demonstrate the API used in Windows classic desktop applications.项目地址https://gitcode.com/gh_mirrors/wi/Windows-classic-samples点击查看免费下载相关推荐Swift Package Manager 插件中的 SourceModuleTarget源码模块目标探测 API 全面解析Swift Package Manager 插件中的 SourceModuleTarget源码模块目标探测 API 全面解析 SourceModuleTarg示例工程ESP32 USB Hub 双摄像头示例基于 esp-iot-solution 与 usb_host_uvc 的多路 UVC 摄像头 HTTP 预览实战ESP32 USB Hub 双摄像头示例基于 esp iot solution 与 usb_host_uvc 的多路 UVC 摄像头 HTTP 预览实战 本篇物联网嵌入式驱动开发硬件开发从零部署 Greenlight v3基于 BigBlueButton 的会议门户安装与 .env 配置全指南从零部署 Greenlight v3基于 BigBlueButton 的会议门户安装与 .env 配置全指南 Greenlight 是 BigBlueButt示例工程上一篇为什么四足机器人开发如此困难斯坦福Pupper V3用开源方案为你破局下一篇tiny11builder精简Windows 11完全指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑