DirectShow读取摄像头数据


***【在线视频教程】***

好文章,来自【福优学苑@音视频+流媒体】


DirectShow的概念

DirectShow GraphEdit(graphedt.exe)来进行分析:

image.png


在上图中可以直观的看到播放这个媒体文件的基本模块,七个模块按广度顺序:读文件模块, 解复用模块, 视频解码模块, 音频解码音频, 颜色空间转换模块,视频显示模块,

音频播放模块。

按照DirectShow的称呼, 一个模块叫做一个filter(过滤器),模块的输入输出口叫做pin(管脚), 有input pin 和output pin两种; 第一个filter叫做Source filter, 每种媒体最后一个filter叫做Sink filter, 如上图所示连成串的所有filter组成一个Graph, 媒体文件的数据就像流水一样在Graph中流动, 各个相关的filter各司其职, 最后我们就看到了视频,也听到了声音(松耦合、高内聚)。


功能模块与组件分析

DirectShow中和播放器有关的filter粗略的分为五类, 分别是Source filter, Demux fiter,

Decoder filter, Color Space converter filter, Render filter,  各类的filter的功能与作用简述如下:

Source filter:源过滤器, 它的作用是为下级的demux filter以包的形式源源不断的提供数据流。在通常情况下,我们有多种方式可以获得数据流, 一种是从本地文件中读取,一种是从网上获取, Sourcefilter另外的一个作用就是屏蔽读本地文件和获取网络数据的差别,

在下一级的demux filter看来,本地文件和网络数据是一样的。总结一下, Sourcefilter有两个作用:其一是为下一级的demux filter提供数据流, 其二是屏蔽读本地文件和获取网络数据的差别即对于下一级的demux filter看来,本地文件和网络数据是一样的。


  Demux filter:解复用过滤器, 它的作用是识别文件类型, 媒体类型, 分离出各媒体的原始数据流, 并打上时钟信息后送给下级的decoder filter。为识别出不同的文件类型和媒体类型,常规的做法是读取一部分数据, 然后遍历解复用过滤器支持的文件格式和媒体数据格式, 做匹配来确定是哪种文件类型,哪种媒体类型;有些媒体类型的原始数据外面还有其他的信息,比如时间,包大小,是否完整包等等。Demux filter解析数据包后取出原始数据, 有些类型的媒体不管是否完整包都立即送往下级的decoder filter, 有些类型的媒体要送完整数据包, 此时可能有一些数据包拼接的动作;当然时钟信息的计算也是demux filter的工作内容, 这个时钟用于各媒体之间的同步。例如, AVI Splitter是Demux filter。


Decoder filter:解码过滤器的作用就是解码数据包,并且把同步时钟信息传递下去,对视频媒体而言,通常是解码成YUV数据,然后利用显卡硬件直接支持YUV格式数据Overlay快速显示的特性让显卡极速显示。YUV格式是一个统称, 常见的有YV12, YUY2, UYVY等等。有些非常古老的显卡和嵌入式系统不支持YUV数据显示, 那就要转换成RGB格式的数据, 每一帧的每一个像素点都要转换, 分别计算RGB分量,并且因为转换是浮点运算, 虽然有定点算法, 还是要耗掉相当一部分CPU,总体上效率低下。对音频媒体而言, 通常是解码成PCM数据,然后送给声卡直接输出, 在本例中,  AVI Decompress和ACM Warper是decoder filter。

Color space converter filter: 颜色空间转换过滤器,它的作用是把视频解码器解码出来的数据转换成当前显示系统支持的颜色格式。通常视频解码器解码出来的是YUV格式, PC系统是直接支持YUV格式的, 也支持RGB格式, 有些嵌入式系统只支持RGB格式。在本例中,视频解码器解码出来的是RGB8格式的数据, Color space converter filter把RGB8转换为RGB32显示。

Render filter:渲染过滤器, 它的作用是在适当的时间渲染相应的媒体,对视频媒体就是直接显示图像, 对音频就是播放声音。视音频同步的策略方法有好几种,其中最简单的一种就是默认视频和音频基准时间相同, 这时音频可以不打时钟信息,通过计算音频的采样频率,量化bit数, 声道数等基本参数就知道音频PCM的数据速率,按照这个速率往前播放即可;视频必须要使用同步时钟信息来决定什么时候显示。DirectShow采用一个有序链表,把接受到的数据包放进有序连表中,启动一个定时器, 每次定时器时间就扫描链表,比较时钟信息,或者显示相应的帧,或者什么也不做,每次收到新的数据帧,首先判断时钟信息,如果是历史数据帧就丢弃,如果是将来显示的数据帧就存放在有序链表,如果是当前时间帧就直接显示。如果这样,保持视频和音频在人体感觉误差范围内相对的动态同步。在本例中VideoRender和Default DirectSound Device是Render filter, 同时也是Sink filter。

GraphEdit应用程序:它可以看成是一个支撑平台,支撑框架。它容纳各种filter,在filter间的传递一些通讯消息, 控制filter的运行(启动暂停停止),维护filter运行状态。GraphEdit就像超级大管家一样, 既维护管理看得见的filter,又维护管理看不见的运行支持环境。

通过上面的讲述,希望能对多媒体的框架的基本元素有一定的了解,虽然ffmpeg库自成一体,但是也是能够归纳到上面的流程之中的。


知识普及:

(一)  YUV: 主要用于优化彩色视频信号的传输,使其向后相容老式黑白电视。与RGB视频信号传输相比,它最大的优点在于只需占用极少的频宽(RGB要求三个独立的视频信号同时传输)。其中“Y”表示明亮度(Luminance或Luma),也就是灰阶值;而“U”和“V” 表示的则是色度(Chrominance或Chroma)。

(二)PCM:主要过程是将话音、图像等模拟信号每隔一定时间进行取样,使其离散化,同时将抽样值按分层单位四舍五入取整量化,同时将抽样值按一组二进制码来表示抽样脉冲的幅值。


DirectShow框架与流程

DirectShow(简称 DShow) 是一个 Windows 平台上的流媒体框架,提供了高质量的多媒体流采集和回放功能。它支持多种多样的媒体文件格式,包括 ASF、MPEG、AVI、MP3和WAV 文件,同时支持使 动或早期的 VFW 驱动来进行多媒体流的采集。


DirectShow 大大简化了媒体回放、格式转换和采集工作。但与此同时,它也为用户自定义的解决方案提供了底层流控制框架,从而使用户可以自行创建支持新的文件格式或其他用户的 DirectShow 组件。


DirectShow 专为 C ++ 而设计。 Microsoft 不提供用于 DirectShow 的托管 API。


DirectShow 是基于组件对象模型(COM)的,因此当你编写 DirectShow 应用程序时,你必须具备 COM 客户端程序编写的知识。对于大部分的应用程序,你不需要实现自己的 COM 对象,DirectShow 提供了大部分你需要的 DirectShow 组件,但是假如你需要编写自己的 DirectShow 组件来进行扩充,那么你必须编写实现 COM 对象。


使用 DirectShow 编写的典型应用程序包括:DVD 播放器、视频编辑程序、AVI 到 ASF 转换器、 MP3 播放器和数字视频采集应用。




DirectShow 架构

DirectShow 的架构如下图所示:

image.png




DirectShow 位于应用层中。它使用一种叫 Filter Graph 的模型来管理整个数据流的处理过程;参与数据处理的各个功能模块叫 Filter;各个 Filter 在 Filter Graph 中按一定的顺序连接成一条 "流水线" 协同工作。( 可以看出 FilterGraph 是 Filter 的容器 )



按照功能来分,Filter 大致分为三类:

Source Filters、Transform Filters 和 Rendering(sink) Filters。


Source Filters 主要负责取得数据,数据源可以是文件、因特网、或者计算机里的采集卡、数字摄像机等,然后将数据往下传输;

Transform Fitlers 主要负责数据的格式转换、传输;

Rendering Filtes 主要负责数据的最终去向,我们可以将数据送给声卡、显卡进行多媒体的演示,也可以输出到文件进行存储。

在 DirectShow 系统上,我们看到的,即是我们的应用程序(Application)。应用程序要按照一定的意图建立起相应的 Filter Graph,然后通过 Filter Graph Manager 来控制整个的数据处理过程。DirectShow 能在 Filter Graph 运行的时候接收到各种事件,并通过消息的方式发送到我们的应用程序。这样,就实现了应用程序与 DirectShow 系统之间的交互。




DirectShow使用一种交Filter Graph的模型来管理整个数据流的处理过程;参与数据处理的各个功能模块叫做Filter;各个Filter在Filter Graph中按一定的顺序连接成一条"流水线"协同工作。Filter,它是最基本的软件构件,过滤器通常在多媒体流中执行一个操作。各个Filter在Filter Graph中按一定的顺序连接成一条"流水线"协同工作。如果用图论的术语描述,过滤器图是一个有向、无环、非连通图。有向是因为数据在过滤器之间以预定的方向流动;无环是指没有路径可以从一个过滤器出发又返回到它自身;而非连通是指不是所有的过滤器都可以达到所有其他过滤器。




FFmpeg+DirectShow

ffmpeg -list_devices true -f dshow -i dummy

命令执行后输出的结果如下(注:中文的设备会出现乱码的情况)。

列表显示设备的名称很重要,输入的时候都是使用“-f dshow -i video="{设备名}"”的方式。

获取摄像头数据(保存为本地文件或者发送实时流)



编码为H.264,保存为本地文件

下面这条命令,实现了从摄像头读取数据并编码为H.264,最后保存成mycamera.mkv。


ffmpeg -f dshow -i video="USB2.0 PC CAMERA" -vcodec libx264 mycamera001.mkv



ffplay直接播放摄像头的数据

使用ffplay可以直接播放摄像头的数据,命令如下:

ffplay -f dshow -i video="USB2.0 PC CAMERA"

如果设备名称正确的话,会直接打开本机的摄像头,


DirectShow编码实战


image.png



好文章,来自【福优学苑@音视频+流媒体】
***【在线视频教程】***