手机直播系统偶尔会需要到的:Windows 下视频采集技术

Posted cdnfast

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手机直播系统偶尔会需要到的:Windows 下视频采集技术相关的知识,希望对你有一定的参考价值。

Windows下视频采集的方法

在 Windows 下主要有两种方法来采集视频: 一种是通过 Media Foundation,另一种是通过 DirectShow。

Meida Foundation 是 Windows 从 vista 之后推出的一套全新的 多媒体SDK,简单方便,从 Win7 开始成熟起来。

另一种是 DirectShow,它主要用于 win7 之前的采集视频。使用 DirectShow 编写代码比较麻烦,主要是因为 Windows 工程师按照逻辑电路的思维方式设计了 DirectsShow 的开发接口,引入了什么 filter, pin之类的概念。这些老掉牙的东西现在估计没几个人能搞明白,除非你是从那个时代过来的,哈哈。

这也解释了为啥现在很少有人学习 Windows 程序开发了,就是因为跟不上时代。你看人家 androidios做视频采集多简单,你整的这么麻烦,谁还愿意学!

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

CoInitializeEx(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 Reader

IMFSourceReader *soureReader = NULL;

//通过媒体源和请求命令,可以获取source reader。(第二种开发模型)
MFCreateSourceReaderFromMediaSource(
                mediaSource,
                videoCmd,
                &sourceReader);

设置 Media Type

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);

读取数据

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 采集视频。

以上是关于手机直播系统偶尔会需要到的:Windows 下视频采集技术的主要内容,如果未能解决你的问题,请参考以下文章

在Windows下搭建基于nginx的视频直播和点播系统

类似快手抖音手机直播程序搭建经验分享

Windows平台基于RTMP实现一对一互动直播

带你了解直播系统的架构

基于手机4G信号做现场视频直播的教程,实现全终端可以观看

第三十二篇直播项目开发