前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Windows 下视频采集

Windows 下视频采集

作者头像
音视频_李超
发布2020-04-02 18:10:07
2.8K1
发布2020-04-02 18:10:07
举报
前言

这两天一直在分析 Windows 下 WebRtc 的代码,所以有些日子没有写东西了。今天来聊聊Windows 下的视频采集。

现在在网上查 Windows 相关的技术可不容易。在百度上能查到的资料基本是 2014 年之前的文章,可以看出这两年 Windows 下滑的有多厉害。Google 又无法使用,真是让人欲哭无泪啊。

废话少说,咱们还是直入正题。

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 找到。下面的文字基本是翻译的 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 Pipeline

Media Pipeline 包括三种类型对象:Media Sources、MFTs(Media Foundation Transfors)、Media Sink。

  • Media Sources: 将数据引入到管道里。数据可以来自本地文件,网络流或都是硬件设备。
  • MFTs: 处理流数据。在 MFTs 里实现了编解码器。
  • Media Sink: 消费数据。显示视频到显示屏上,播放声音或写数据到媒体文件。

Media Session 通过管道控制数据流。如质量控制,音频/视频同步,格式的改变。

Source Reader 和 Sink Writer

Source 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 组件并启动 MF

代码语言:javascript
复制
...
CoInitializeEx(NULL, COINIT_APARTMENTTHREAD | COINIT_DISABLE_OLEDDE)
MFStartup(MF_VERSION)
...

获取所有的视频设备

代码语言:javascript
复制
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); //这里存放的是设备的个数
...

�激活某个视频设备

代码语言:javascript
复制
IMFMediaSource *mediaSource = NULL;
...
//激活第一个视频设备,并为该设置备生成逻辑上的媒体源(Media Source)
videoDevices[0]->ActivateObject(IID_PPV_ARGS(&mediaSource));
...

创建 Source Reader

代码语言:javascript
复制
IMFSourceReader *soureReader = NULL;
...
//通过媒体源和请求命令,可以获取source reader。(第二种开发模型)
MFCreateSourceReaderFromMediaSource(
                mediaSource,
                videoCmd,
                &sourceReader);
...

设置 Media Type

代码语言:javascript
复制
IMFMediaType *mediaType = NULL;
...
MFCreateMediaType(&mediaType);
//设置媒体为视频
mediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
//YUV格式为 I420
mediaType->SetGUID(MF_MT_SUBTYPE, WMMEDIASUBTYPE_I420); 
//每个视频帧的大小为 640 * 480
MFSetAttributeSize(mediaType, MF_MT_FRAME_SIZE, 640, 480);
sourceReader->SetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM,
                         NULL,
                         mediaType);

读取数据

代码语言:javascript
复制
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 采集视频。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Windows下视频采集的方法
  • Media Foundation的一些概念
    • Primitives 和 Platfrom
      • Media Pipeline
        • Source Reader 和 Sink Writer
        • 采集视频数据
          • MF采集视频的基本步骤
            • 详细分析
            • 小结
            相关产品与服务
            容器服务
            腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档