视频采集 via Media Foundation
Media Foundation 简介
Media Foundation (简称 MF)是微软在 Windows Vista上 推出的新一代多媒体应用库,目的是提供 Windows 平台一个统一的多媒体影音解决方案,开发者可以通过 MF 播放视频或声音文件、进行多媒体文件格式转码,或者将一连串图片编码为视频等等。
MF 是 DirectShow 为主的旧式多媒体应用程序接口的替代者与继承者,在微软的计划下将逐步汰换 DirectShow 技术。MF 要求 Windows Vista 或更高版本,不支持较早期的 Windows 版本,特别是 Windows XP。
MF 长于高质量的音频和视频播放,高清内容(如 HDTV,高清电视)和数字版权管理(DRM)访问控制。MF 在不同的 Windows 版本上能力不同,如 Windows 7 上就添加了 h.264 编码支持。Windows 8 上则提供数种更高质量的设置。
MF 提供了两种编程模型,第一种是以 Media Session 为主的 Media pipeline 模型,但是该模型太过复杂,且曝露过多底层细节,故微软于 Windows 7 上推出第二种编程模型,内含 SourceReader、Transcode API 、SinkWriter 及 MFPlay 等高度封装模块,大大简化了 MF 的使用难度。
# 本文使用了第二种(简单的)编程模型。
Media Foundation 采集视频
采集流程图
MF 采集视频代码
以下是整个 MF 采集过程的概要代码,略去设备枚举和 CMFCapture 类的实现
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
hr = MFStartup(MF_VERSION);
// Enumerate the capture devices.
hr = UpdateDeviceList(hDlg, true);
EncodingParameters vidEncParam;
vidEncParam.subType = _getSubType(hDlg, false);
vidEncParam.bitRate = TARGET_VID_BIT_RATE;
CComPtr<IMFActivate> pVidActivate = NULL;
hr = GetSelectedDevice(hDlg, &pVidActivate, true);
hr = CMFCapture::CreateInstance(hDlg, &g_pCapture);
hr = g_pCapture->startCapture(pVidActivate, &vidEncParam, pszFile);
// Capturing ...
hr = g_pCapture->stopCapture();
g_pCapture->Release();
MFShutdown();
CoUninitialize();
MMDeviceHelper::enumVidCapDevices 函数
此处使用了 _enumMFDevices 传参的形式获取视频设备,因为该函数还可以枚举音频设备。
HRESULT MMDeviceHelper::enumVidCapDevices()
{
return _enumDevices(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID);
}
HRESULT MMDeviceHelper::_enumMFDevices(const GUID& devType)
{
HRESULT hr = S_OK;
CComPtr<IMFAttributes> pAttributes = NULL;
clear();
// Initialize an attribute store. We will use this to specify the enumeration parameters.
hr = MFCreateAttributes(&pAttributes, 1);
RETURN_IF_FAILED(hr);
hr = pAttributes->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, devType);
RETURN_IF_FAILED(hr);
hr = MFEnumDeviceSources(pAttributes, &m_ppDevices, &m_cDevices);
RETURN_IF_FAILED(hr);
return hr;
}
CMFCapture::startCapture 函数
首先创建一个 Sink Writer 并开始写入,接着配置视频输入并开始读取 sample。
HRESULT CMFCapture::startCapture(IMFActiv