摘要:DirectShowLib是对微软DirectShow的C#开源封装。在介绍DirectShowLib的基础上,基于DirectShowLib类库,设计并实现了一个家庭视频监控系统原型,通过对USB无驱摄像头的操控,实现视频的采集、抓图和录像功能,可满足一般家庭安防系统中的实时视频监控的需要。
关键字:DirectShow,视频监控,家庭安防,C#
1引言
视频监控是通过获取监控目标的视频图像信息,对视频图像进行监视、记录、回溯,并根据视频图像信息人工或自动地做出相应的动作,以达到对监控目标的监视、控制、安全防范、和智能管理等目的。随着网络通讯技术及图像压缩处理技术以及传输技术的快速发展,使得家庭能够采用最新的视频压缩和图像处理技术,通过USB摄像头采集视频图像,可实现家庭环境的实时视频监控。
为了免除越来越多的城市白领阶层对家人健康和家庭财产安全的后顾之忧,市场上有不少家庭视频监控系统,比如基于数字视频录像机DVR的网络化家庭监控系统、环球眼视频监控系统等。虽然它可使得你无论身在全球何处都可以通过互联网和全球移动通信系统随时监控家庭的安全环境,但是这样的监控系统部署困难,价格昂贵,对一般家庭的计算机用户来说,不太适合。一般用户来说,家庭拥有普通计算机、网络和USB摄像头,而市场上的视频监控系统一般要求的是专业的摄像头和网络终端,而且视频监控软件的价格比较高,对普通用户来说,必要性不大。
为此,针对一般家庭用户,我们提出了一种简单有效的家庭视频监控系统实现方法,可方便用户自行设计、搭建一个比较实用的家庭安防系统。DirectShowLib 是一个对微软的功能强大的DirectShow的C#开源封装的类库,可实现对视频音频的采集、编码、压缩和处理。一般家庭用户中,使用的摄像头基本上是USB的无驱摄像头,所以我们可以基于该类库,在VS2008开发环境下,使用C#语言,操作控制USB摄像头,设计并实现一套家庭视频监控系统,通过视频采集、录像等功能,实现对家庭环境的视频监控。
2 DirectShowLib类库
DirectShowLib是kawaic,snarfle等人对微软DirectShow的C#开源封装,目的是使C#开发者也能方便的使用DirectShow。有了该lib,在C#下开发视频采集等已经不在是难事。DirectShow是微软公司在ActiveMovie和Video for Windows的基础上推出的新一代基于COM(Component Object Model)的流媒体处理的开发包,与DirectX开发包一起发布。DirectShow使用一种叫Filter Graph的模型来管理整个数据流的处理过程,运用DirectShow,我们可以很方便地从支持WDM驱动模型的采集卡上捕获数据,并且进行相应的后期处理乃至存储到文件中。它广泛地支持各种媒体格式,包括Asf、Mpeg、Avi、Dv、Mp3、Wave等,为多媒体流的捕捉和回放提供了强有力的支持。
DirectShow 运行的方式通常是一个开发者创建一个Filter Graph,把一些Filter,加入 Filter Graph,然后播放文件,或者播放来自互联网或照相机的数据。当播放进程运行时,Filter Graph在Windows注册中寻找注册了的Filters,并且为这些Filter创建本地提供的Graph。在这之后,它将所有的Filter连接在一起,并且在开发者的请求下,播放/中止创造的Graph。在 DirectShow 中有许多抽象的播放源文件的方法,实现这些功能也是相当简单的而且不需要一个定制过的filter。
既然DirectShowLib是对DirectShow的封装,那么它自然也可以实现DirectShow的各种功能,其使用和调用方法与DirectShow是一样的。这里仅介绍在视频监控系统中必要的几种接口对象的方法,具体实现中,这些方法都包含在一个单独的类文件中,如Capture.cs。
(1)获取视频采集设备IBaseFilter接口对象的方法
//获取所有视频设备名称
public ArrayList GetVideoInputDevice()
{
return GetDeviceCollection(FilterCategory.VideoInputDevice);
}
private ArrayList GetDeviceCollection(Guid DeviceType)
{
ArrayList returnString = new ArrayList();
foreach (DsDevice ds in DsDevice.GetDevicesOfCat(DeviceType))
{
returnString.Add(ds.Name);
}
return returnString;
}
//通过获取到的视频设备名称设置采集设备的IBaseFilter对象
public bool SetVideoInputDevice(string VideoInputDeviceName)
{
//创建视频输入设备接口
theVideoDevice=CreateFilter(FilterCategory.VideoInputDevice, VideoInputDeviceName);
}
//通过过滤器类型和过滤器名称获取IBaseFilter接口
private IBaseFilter CreateFilter(Guid category, string friendlyname)
{
object source = null;
Guid iid = typeof(IBaseFilter).GUID;
foreach (DsDevice device in DsDevice.GetDevicesOfCat(category))
{
if (device.Name.CompareTo(friendlyname) == 0)
{
device.Mon.BindToObject(null, null, ref iid, out source);
break;
}
}
return (IBaseFilter)source;
}
(2)初始化基本的接口对象方法
private void InitInterfaces()
{
int hr = 0;
// 获取IGraphBuilder接口对象
this.m_graphBuilder = (IGraphBuilder)new FilterGraph();
//获取ICaptureGraphBuilder2接口对象
this.m_captureGraphBuilder= (ICaptureGraphBuilder2) new CaptureGraphBuilder2();
//获取m_graphBuilder 接口对象的IMediaControl对象
this.m_mediaControl = (IMediaControl)this.m_graphBuilder;
//获取m_graphBuilder 接口对象的IVideoWindow对象
this.m_videoWindow = (IVideoWindow)this.m_graphBuilder;
//获取m_graphBuilder 接口对象的IMediaEventEx对象
this.m_mediaEventEx = (IMediaEventEx)this.m_graphBuilder;
//设置ICaptureGraphBuilder2的IGraphBuilder接口对象为当前对象
hr = this.m_captureGraphBuilder.SetFiltergraph(this.m_graphBuilder);
DsError.ThrowExceptionForHR(hr);
//注册事件到应用程序的窗体上
hr=this.m_mediaEventEx.SetNotifyWindow(this.hwnPropertyPageOwner, WM_GRAPHNOTIFY, IntPtr.Zero);
DsError.ThrowExceptionForHR(hr);
}
|