<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
想使用ffmpeg開啟攝像頭,需要輸入攝像頭的名稱,而ffmpeg本身的列舉攝像頭列表功能不是介面
,所以需要用其他方式獲取到裝置列表。C++獲取視訊裝置列表的方法有不少,但C#獲取視訊裝置列表的方法網上提供的解決方案基本都是依賴第三方庫的,為了獲取視訊裝置列表而引入一整個視訊庫實在是不太必要。經過思考,Windows的directshow和mediafudation都是基於com的,而且C#對com的支援是很好的,基於上述兩點我們完全可以在C#中直接呼叫com。
我們使用directshow獲取視訊裝置列表,由於com的跨語言特性,完全可以直接在C#中呼叫,而不用通過C++封裝一層dll給C#使用。我們首先定義需要的com物件介面。
static readonly Guid SystemDeviceEnum = new Guid(0x62BE5D10, 0x60EB, 0x11D0, 0xBD, 0x3B, 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86); static readonly Guid VideoInputDevice = new Guid(0x860BB310, 0x5D01, 0x11D0, 0xBD, 0x3B, 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86); [Flags] enum CDef { None = 0x0, ClassDefault = 0x1, BypassClassManager = 0x2, ClassLegacy = 0x4, MeritAboveDoNotUse = 0x8, DevmonCMGRDevice = 0x10, DevmonDMO = 0x20, DevmonPNPDevice = 0x40, DevmonFilter = 0x80, DevmonSelectiveMask = 0xF0 } [ComImport] [SuppressUnmanagedCodeSecurity] [Guid("3127CA40-446E-11CE-8135-00AA004BB851")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IErrorLog { [PreserveSig] int AddError([In][MarshalAs(UnmanagedType.LPWStr)] string pszPropName, [In] System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo); } [ComImport] [Localizable(false)] [SuppressUnmanagedCodeSecurity] [Guid("55272A00-42CB-11CE-8135-00AA004BB851")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IPropertyBag { [PreserveSig] int Read([In][MarshalAs(UnmanagedType.LPWStr)] string pszPropName, [MarshalAs(UnmanagedType.Struct)] out object pVar, [In] IErrorLog pErrorLog); [PreserveSig] int Write([In][MarshalAs(UnmanagedType.LPWStr)] string pszPropName, [In][MarshalAs(UnmanagedType.Struct)] ref object pVar); } [ComImport] [SuppressUnmanagedCodeSecurity] [Guid("29840822-5B84-11D0-BD3B-00A0C911CE86")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface ICreateDevEnum { [PreserveSig] int CreateClassEnumerator([In][MarshalAs(UnmanagedType.LPStruct)] Guid pType, out IEnumMoniker ppEnumMoniker, [In] CDef dwFlags); }
與directshow流程一樣,呼叫com列舉裝置即可,本文只展示獲取裝置名稱(FriendlyName),獲取其他屬性可以參照c++呼叫directshow的實現。
/// <summary> /// 列舉視訊裝置 /// </summary> public static IEnumerable<string> Devices { get { IMoniker[] monikers = new IMoniker[5]; var devEnum = Activator.CreateInstance(Type.GetTypeFromCLSID(SystemDeviceEnum)) as ICreateDevEnum; IEnumMoniker moniker; if (devEnum.CreateClassEnumerator(VideoInputDevice, out moniker, 0) == 0) { while (true) { int r = moniker.Next(1, monikers, IntPtr.Zero); if (r != 0 || monikers[0] == null) break; yield return GetName(monikers[0]); foreach (var i in monikers) { if(i!=null) Marshal.ReleaseComObject(i); } } Marshal.ReleaseComObject(moniker); } Marshal.ReleaseComObject(devEnum); } } /// <summary> /// 獲取裝置名稱 /// </summary> /// <param name="moniker"></param> /// <returns></returns> static string GetName(IMoniker moniker) { IPropertyBag property; object value; object temp = null; try { Guid guid = typeof(IPropertyBag).GUID; moniker.BindToStorage(null, null, ref guid, out temp); property = temp as IPropertyBag; int hr = property.Read("FriendlyName", out value, null); Marshal.ThrowExceptionForHR(hr); return value as string; } catch (Exception) { return null; } finally { if (temp != null) { Marshal.ReleaseComObject(temp); } } }
using System; using System.Collections.Generic; using System.ComponentModel; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; using System.Security; namespace AC { public class EnumDevices { /// <summary> /// 列舉視訊裝置 /// </summary> public static IEnumerable<string> Devices { get { IMoniker[] monikers = new IMoniker[5]; var devEnum = Activator.CreateInstance(Type.GetTypeFromCLSID(SystemDeviceEnum)) as ICreateDevEnum; IEnumMoniker moniker; if (devEnum.CreateClassEnumerator(VideoInputDevice, out moniker, 0) == 0) { while (true) { int hr = moniker.Next(1, monikers, IntPtr.Zero); if (hr != 0 || monikers[0] == null) break; yield return GetName(monikers[0]); foreach (var i in monikers) { if(i!=null) Marshal.ReleaseComObject(i); } } Marshal.ReleaseComObject(moniker); } Marshal.ReleaseComObject(devEnum); } } /// <summary> /// 獲取裝置名稱 /// </summary> /// <param name="moniker"></param> /// <returns></returns> static string GetName(IMoniker moniker) { IPropertyBag property; object value; object temp = null; try { Guid guid = typeof(IPropertyBag).GUID; moniker.BindToStorage(null, null, ref guid, out temp); property = temp as IPropertyBag; int hr = property.Read("FriendlyName", out value, null); Marshal.ThrowExceptionForHR(hr); return value as string; } catch (Exception) { return null; } finally { if (temp != null) { Marshal.ReleaseComObject(temp); } } } static readonly Guid SystemDeviceEnum = new Guid(0x62BE5D10, 0x60EB, 0x11D0, 0xBD, 0x3B, 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86); static readonly Guid VideoInputDevice = new Guid(0x860BB310, 0x5D01, 0x11D0, 0xBD, 0x3B, 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86); [Flags] enum CDef { None = 0x0, ClassDefault = 0x1, BypassClassManager = 0x2, ClassLegacy = 0x4, MeritAboveDoNotUse = 0x8, DevmonCMGRDevice = 0x10, DevmonDMO = 0x20, DevmonPNPDevice = 0x40, DevmonFilter = 0x80, DevmonSelectiveMask = 0xF0 } [ComImport] [SuppressUnmanagedCodeSecurity] [Guid("3127CA40-446E-11CE-8135-00AA004BB851")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IErrorLog { [PreserveSig] int AddError([In][MarshalAs(UnmanagedType.LPWStr)] string pszPropName, [In] System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo); } [ComImport] [Localizable(false)] [SuppressUnmanagedCodeSecurity] [Guid("55272A00-42CB-11CE-8135-00AA004BB851")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IPropertyBag { [PreserveSig] int Read([In][MarshalAs(UnmanagedType.LPWStr)] string pszPropName, [MarshalAs(UnmanagedType.Struct)] out object pVar, [In] IErrorLog pErrorLog); [PreserveSig] int Write([In][MarshalAs(UnmanagedType.LPWStr)] string pszPropName, [In][MarshalAs(UnmanagedType.Struct)] ref object pVar); } [ComImport] [SuppressUnmanagedCodeSecurity] [Guid("29840822-5B84-11D0-BD3B-00A0C911CE86")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface ICreateDevEnum { [PreserveSig] int CreateClassEnumerator([In][MarshalAs(UnmanagedType.LPStruct)] Guid pType, out IEnumMoniker ppEnumMoniker, [In] CDef dwFlags); } } }
.net 6.0程式碼範例如下
// See https://aka.ms/new-console-template for more information using AC; //列舉裝置 foreach (var i in EnumDevices.Devices) { //列印裝置名稱 Console.WriteLine(i); }
效果:
以上就是今天要講的內容,本文介紹了C#直接呼叫com獲取視訊裝置列表的方法,只要知道了com的一些基本原理以及c#和com的關係,很容易就能實現c#直接使用directshow的功能,第三方的庫也是做了類似的工作,定義了完整的directshow的介面,只是筆者使用的環境中只需要列舉視訊裝置列表,不需要其他功能,引入完整的directshow介面有點大材小用,所以還不如自己定義幾個必要的介面來的實在。
到此這篇關於C# 使用com獲取Windows攝像頭列表的文章就介紹到這了,更多相關C# 獲取Windows攝像頭列表內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45