DirectShow 视频采集

DirectShow 视频采集

视频采集模块主要完成的功能是枚举视频采集设备生产列表;枚举音频采集设备生成列表;枚举视频采集设备上支持的所有视频格式;枚举音频采集设备上支持的所有音频格式;调整采集设备输出图像的显示参数;实时保存采集的视频文件。

视频采集设备枚举

DirectShow使用特殊的Filter对视频采集设备进行封装,WDM驱动模型的视频采集设备使用WDM Video CaptureFilter,VFW驱动模型的采集设备使用VFW CaptureFilter。只要视频采集设备正确安装,DirectShow就能把它封装成一个Filter,注册在特定目录下。

系统中的硬件是不可预知的,通过系统枚举的方式枚举某个目录下的所有Filter,从枚举出的Filter选择要使用的Filter。视频采集设备注册在Video Capture Sources目录下,应用程序主要枚举该目录,就能直到系统中安装有多少个、以及何种类型的视频采集设备。DirectShow提供了一个专门的系统枚举组件(CLSID_SystemDeviceEnum),其枚举过程如下图所示:

  • 1)使用CoCreateInstance函数创建系统枚举器组件对象,并获得ICreateDevEnum接口;

  • 2)使用接口方法ICreateDevEnum::CreateClassEnumerator为指定的Filter注册类型目录创建一个枚举器(参数类型为CLSID_VideoInputDeviceCategory),并获得IEnumMoniker接口;

  • 3)使用IEnumMoniker::Next接口方法枚举指定类型目录下所有设备,每个设备上都实现了IMoniker接口;

  • 4)调用IMoniker::BindToStorage之后,可以访问设备标识的属性集,得到DispalyName、Freuendly name等;

  • 5)调用IMoniker::BindToObject可以将设备标识生成一个DirectShow Filter。

随后调用IFilterGraph::AddFilter将之加入到Filter Graph中参与工作。

音频采集设备的枚举过程与视频采集设备的枚举过程是一样的,不同点是音频采集注册的跟目录和视频采集设备的根目录不同。

视频参数设置

在视频预览或采集之前,需要设置视频参数。这些参数包括采集图像的大小,帧率,输出格式,图像显示的亮度、对比度、色调、饱和度等。对于WDM卡,可以通过IAMStreamConfig接口和IAMVideoProcAmp接口编程来实现。

首先获得Preview Pin或者Capture Pin上的IAMStreamConfig接口 ,通过ICaptureGraphBuilder2::FindInterface设置视频参数。

典型情况下,采集卡可以输出多个格式,如16位或32位的RGB格式、YUYV格式等。通过接口方法IAMStreamConfig::GetNumberOfCapabilities和IAMStreamConfig::GetStreamCaps枚举采集卡支持的输出格式。第一个函数返回Pin上支持的输出格式的数量,描述输出格式的数据结构的大小。IAMStreamConfig接口即可用于视频格式的配置,也可用于音频格式的配置。视频使用VIDEO_STREAM_CONFIG_CAPS数据结构,音频使用AUDIO_STREAM_CONFIG_CAPS数据结构,通过数据结构的大小判断使用的数据结构类型。

同时,在采集过程中,需要调节获取当前图像的显示参数,如图像显示的亮度、色调、饱和度等。视频采集Filter通过IAMVideoProcAmp接口的Get方法获取当前使用的图像显示参数,Set方法设置图像的显示参数类型改变图像的亮度等显示信息。

视频编码选择

在视频采集过程中,选择一种对视频有效的编码很重要,编码质量不但高,且能满足视频采集实时的需要,通过对与个主要标准的介绍,综合分析:M-JPEG压缩率太小,而且对硬件的要求太高;H.26x系列,算法较成熟,而且有很多参数可以调整,能够适合多种情况,经过适当设置可以在算法复杂度和实时性要求上满足视频压缩技术项目要求;MPEG系统算法成熟度高,标准完整详细,尤其是其中的MPEG-4标准,采用了基于对象的方法,非常适合视频采集压缩技术项目中背景不变的视频流,并且在软件方面,XviD组织提供了完善的可运行的Filter组件,可以免费使用。

在实时采集中,大部分项目压缩都是由硬件来完成,成本较高。综合系统的各个方面,最终选定了Xvid组织Filter实现视频的压缩。

视频采集实现

DirectShow框架下,所有功能的实现都是基于Filter的,单个Filter没有数据的流动,只有将各个功能的Filter连成一条链路,Filter Graph Manager统一管理,实现数据的流动,才能完成一定的功能。

实现采集应用的Filter Graph比较复杂。DirectShow提供了辅助组件CaputerGraphBuilder简化了采集Filter Graph的创建,该组件暴露了ICaptureGraphBuilder2接口。接口上AllocCapFile方法设置采集文件的大小,ControlStream方法控制采集数据的每路流的开始时间与结束时间,控制各个输出Pin上的数据流的属性设置;CopyCaptureFile方法可以从采集的文件中复制一段保存成新的文件;RenderStream设置采集Filter的输出Pin,流类型,输出Pin的下一级Filter,以及流要压缩的类型;SetFilterGraph设置Filter Graph到Capture Graph Builder组件中;SetOutputFileName设置保存文件的路径与文件类型;FindInterface获得采集链路中的特定功能的Filter,设置数据流的压缩参数和流格式;GetFilterGraph方法获得Filter Graph接口指针。

实现视频采集的流程图如下图所示:

在流程图中,Capture Graph Builder组件初始化是将Filter Graph设置给Capture Graph Builder组件。在连接视频预览分支链路时,当采集卡Filter上有VP Pin时,连接Overlay Mixer2|Video Render;含有Preview Pin时,直接连接Video Render;而只有Capture Pin时,要插入一个Smart Tee Filter进行分路后,再连接到Video Render。在运行过程中,可以改变图像的显示参数,可以实时保存。

热插拔的支持

该系统实现了对音视频采集卡热插拔的支持。一个正在使用的采集卡脱离系统时,Filter Graph Manager会向应用程序发出一个EC_DEVICE_LOST事件;而当这个设备重新介入系统时,Filter Graph Manager会再次发出一个EC_DEVICE_LIST事件。这两次事件通过事件的第二个参数IParam2来区分;0表示设备脱离系统,1表示设备又重新接入系统。实际实现中,设备脱离珍惜爱重新接入后,采集卡Filter先前的状态不会保持下来。因此当获取到设备重新接入的事件,要重建Filter Graph。

另外,当我们的应用程序正在运行时,一个全新的设备接入系统,DirectShow并不会发送EC_DEVICE_LOST事件,在实现中必须依赖窗口消息WM_DEVICEHANGE来做成正确的回应,实现热插拔的支持。

视频采集与预览

视频采集界面包括视频采集设备的选取,视频输出格式的选取,音频采集设备的选取,音频输入Pin(Channel)的选择音频输出格式的选取,视频预览界面,图像显示参数的设置,以及要保存的文件路径。

参考:https://www.yuque.com/docs/share/4ee921de-2d2d-4a5d-a7a4-010c4a9ee54a

好的代码像粥一样,都是用时间熬出来的
原文地址:https://www.cnblogs.com/jijm123/p/14408747.html