Windows下视频采集的方法在 Windows 下主要有两种方法来采集视频: 一种是通过 Media Foundation,另一种是通过 DirectShow。 Meida Foundation 是 Windows 从 vista 之后推出的一套全新的 多媒体SDK,简单方便,从 Win7 开始成熟起来。 另一种是 DirectShow,它主要用于 win7 之前的采集视频。使用 DirectShow 编写代码比较麻烦,主要是因为 Windows 工程师按照逻辑电路的思维方式设计了 DirectsShow 的开发接口,引入了什么 filter, pin之类的概念。这些老掉牙的东西现在估计没几个人能搞明白,除非你是从那个时代过来的,哈哈。这也解释了为啥现在很少有人学习 Windows 程序开发了,就是因为跟不上时代。你看人家 Android/iOS做视频采集多简单,你整的这么麻烦,谁还愿意学!Media Foundation的一些概念 DirectShow 方案我们放到以后再分析,今天我们主要讲下 MediaFoundation 如何进行视频采集。 在讲之前,我们先要补充一些基本概念。这些概念大家可以从[Media Foundation Programming Guide][1] 找到。下面的文字基本是翻译的 Windows 的官方文档。MF(MediaFoundation)的整体结构图如下:MF 提供了两种不同的编程模型。第一种是上图的左半部分,媒体数据通过端到端的管道传递。Application首先初始化管道,然后调用相应方法控制管道中的流。第二种如上图的右半部分,Application可以从 Source Reader拉数据,也可以向 Sink Writer 推数据。这种模型对于处理数据非常有用。 Primitives 和 Platfrom 图底部的 Primitives 是一些辅助API:Attributes: 相当于一个 Map, 由 key/value 组成。Media Type: 描述媒体数据流的格式。Media Buffers: 存放一段媒体数据。Media Samples: 存放 Media Buffers 的容器,相当于一个 Buffter List。MF Platform 提供了一些核心功能的API。例如异步调用、工作队列。Media PipelineMedia Pipeline 包括三种类型对象:Media Sources、MFTs(Media Foundation Transfors)、Media Sink。Media Sources: 将数据引入到管道里。数据可以来自本地文件,网络流或都是硬件设备。MFTs: 处理流数据。在 MFTs 里实现了编解码器。Media Sink: 消费数据。显示视频到显示屏上,播放声音或写数据到媒体文件。Media Session 通过管道控制数据流。如质量控制,音频/视频同步,格式的改变。Source Reader 和 Sink WriterSource Reader 和 Sink Writer提供了使用 Media Foundation 的另一种方法(相较于 media source, transforms, media sink)。Source Reader 控制着 media source 和 多个解码器。Sink Writer 控制着 media sink 和 多个编码器。你可以使用 Source Reader 从 media source 获取到压缩或未压缩的数据,并使用 Sinker Writer 编码数据并发送给 media sink。 下面我们就来看看 MF 是如何采集视频数据的。采集视频数据通过上面的介绍,我们基本可以知道 MF 采用 从源采集数据,编解码,输出渲染这种架构来处理多媒体。这种方式通俗易懂,使用起来非常方便。MF采集视频的基本步骤MF采集数据使用的是架构中的第二种编程模型,其步骤如下:初始化 COM 组件。获取视频设备列表。激活某个视频设备,获取该设备的 Media Source。根据请求命令和 Media Source 创建 Source Reader。为 Source Reader 设置 Media Type。通过 Source Reader 从设备中读取 Media Type 格式的视频数据。以上就是 MF 从视频设备采集数所的基本步骤,下面我们来详细介绍每一步。详细分析由于每一步的代码都实分简单,我这里就不做过多的文字描述了,通过下面的代码及其注释大家很容易理解其中的每一步。初始化 COM 组件并启动 MFCoInitializeEx(NULL, COINIT_APARTMENTTHREAD | COINIT_DISABLE_OLEDDE)MFStartup(MF_VERSION)获取所有的视频设备IMFAttributes *videoCmd = NULL; IMFActivate **videoDevices = NULL;UINT32 videoDeviceCount = 0;//设置获取视频设备的命令MFCreateAttributes(videoCmd, 1/表示只分配一项/);videoCmd->setGUID( MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, //key MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID); //value//获取视频设备列表 MFEnumDeviceSources( videoCmd, &videoDevices, //这里是设备列表 &videoDeviceCount); //这里存放的是设备的个数激活某个视频设备IMFMediaSource *mediaSource = NULL;//激活第一个视频设备,并为该设置备生成逻辑上的媒体源(Media Source)videoDevices[0]->ActivateObject(IID_PPV_ARGS(&mediaSource));创建 Source ReaderIMFSourceReader *soureReader = NULL;//通过媒体源和请求命令,可以获取source reader。(第二种开发模型)MFCreateSourceReaderFromMediaSource( mediaSource, videoCmd, &sourceReader);设置 Media TypeIMFMediaType *mediaType = NULL;MFCreateMediaType(&mediaType);//设置媒体为视频mediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);//YUV格式为 I420mediaType->SetGUID(MF_MT_SUBTYPE, WMMEDIASUBTYPE_I420); //每个视频帧的大小为 640 * 480MFSetAttributeSize(mediaType, MF_MT_FRAME_SIZE, 640, 480);sourceReader->SetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM, NULL, mediaType);读取数据IMFSample *sample = NULL;DWORD index, flags;LONGLONG llVideoTs;while(runing){ sourceReader->ReadSample( MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, &index, //实际流的index &flags, //staus flags &llVideoTs, //时间戳 &sample); //存放采集到的视频数据}通过上面简单的几步,就可以轻松的从视频设备里取到视频数据了。MF相对于 DirectShow真是简单太多了。上面介绍的是使用同步方式使用MF采集视频数据,MF还提供了效率更高的异步方式获取视频数据,有兴趣的朋友可以以本篇文章为基础去学习它的异步方式。小结今天向大家介绍了在 Windows下使用 MF 如何采集视频的方法。通过以下 6 步即可做到:初始化 COM 组件。获取视频设备列表。激活某个视频设备,获取该设备的 Media Source。根据请求命令和 Media Source 创建 Source Reader。为 Source Reader 设置 Media Type。通过 Source Reader 从设备中读取 Media Type 格式的视频数据。另外, MF 的采集方案只适用于 Win7 以后的系统,对于之前的系统还是要使用 DirectShow 方案。我也会在后面再为大家介绍如何使用 DirectShow 采集视频。