摘要: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);
}
|