翼度科技»论坛 编程开发 .net 查看内容

C#调用基于UVC协议的摄像头扩展接口

6

主题

6

帖子

18

积分

新手上路

Rank: 1

积分
18
最近公司增加了一些UVC协议的摄像头接口,下面是一些资料整理(感谢项目组内志宇同学的耐心指导)
摄像头插件为AForge,所以IKsControl接口对象AForge.FilterInfo。(IKsControl接口:提供了控制 KS 过滤器或 KS 引脚的用户模式方法。参考:https://learn.microsoft.com/en-us/windows-hardware/drivers/stream/ks-h-typedef-reference)
  1. /// <summary>
  2.     /// VC01 8K 摄像头 UVC协议扩展接口
  3.     /// </summary>
  4.     public class Vc01UvcExtension
  5.     {
  6.         /// <summary>
  7.         /// 指定标识内核流方法集的 GUID。
  8.         /// </summary>
  9.         private readonly Guid _ksMethodSetGuid = new("A29E7641-DE04-47E3-8B2B-F4341AFF003B");
  10.         private const string Vc01CameraName = "VC01";
  11.         private IKsControl _pControl;
  12.         /// <summary>
  13.         /// 初始化UVC协议扩展接口
  14.         /// </summary>
  15.         /// <param name="cameraName">摄像头名称</param>
  16.         public string Init(string cameraName = "")
  17.         {
  18.             var cameraInfos = CameraDevicesManager.GetCameraInfos();
  19.             if (cameraInfos.Count == 0)
  20.             {
  21.                 return "未接入摄像头";
  22.             }
  23.             if (string.IsNullOrWhiteSpace(cameraName))
  24.             {
  25.                 cameraName = Vc01CameraName;
  26.             }
  27.             var vc01CameraInfo = cameraInfos.FirstOrDefault(cameraInfo => cameraInfo.Name.ToUpper().Contains(cameraName));
  28.             if (vc01CameraInfo == null || string.IsNullOrWhiteSpace(vc01CameraInfo.Identity))
  29.             {
  30.                 return "未接入8K摄像头";
  31.             }
  32.             _pControl = FilterInfo.CreateFilter(vc01CameraInfo.Identity) as IKsControl;
  33.             return _pControl == null ? "转换IKsControl接口失败" : "";
  34.         }
  35.         /// <summary>
  36.         /// 获取UVC扩展属性
  37.         /// </summary>
  38.         /// <param name="type"></param>
  39.         /// <typeparam name="T"></typeparam>
  40.         /// <returns></returns>
  41.         public DvbResult<T> GetUvcExtensionProperty<T>(int type) where T : struct
  42.         {
  43.             var ksProperty = new KsMethod(_ksMethodSetGuid, type, (int)(KsPropertyTypeEnum.KsPropertyTypeGet | KsPropertyTypeEnum.KsPropertyTypeTopology));
  44.             var nod = new KspNode
  45.             {
  46.                 Property = ksProperty,
  47.                 NodeId = 2,
  48.                 Reserved = 0
  49.             };
  50.             var dvbResult = new DvbResult<T>();
  51.             var dataPro = Marshal.AllocHGlobal(Marshal.SizeOf(dvbResult.Data));
  52.             var dataSize = Marshal.SizeOf(dvbResult.Data);
  53.             var dwReturned = 0;
  54.             try
  55.             {
  56.                 var hr = _pControl.KsProperty(ref nod.Property, Marshal.SizeOf(nod), dataPro, dataSize, ref dwReturned);
  57.                 if (hr != 0 || dwReturned != dataSize)
  58.                     return dvbResult;
  59.                 dvbResult.Data = (T)Marshal.PtrToStructure(dataPro, typeof(T));
  60.                 dvbResult.Result = 0;
  61.                 return dvbResult;
  62.             }
  63.             finally
  64.             {
  65.                 Marshal.FreeHGlobal(dataPro);
  66.             }
  67.         }
  68.         /// <summary>
  69.         /// 设置UVC扩展属性
  70.         /// </summary>
  71.         /// <param name="type"></param>
  72.         /// <param name="data"></param>
  73.         /// <typeparam name="T"></typeparam>
  74.         /// <returns></returns>
  75.         public DvbResult SetUvcExtensionProperty<T>(int type, T data) where T : struct
  76.         {
  77.             var ksProperty = new KsMethod(_ksMethodSetGuid, type, (int)(KsPropertyTypeEnum.KsPropertyTypeSet | KsPropertyTypeEnum.KsPropertyTypeTopology));
  78.             var nod = new KspNode
  79.             {
  80.                 Property = ksProperty,
  81.                 NodeId = 2,
  82.                 Reserved = 0
  83.             };
  84.             var dvbResult = new DvbResult();
  85.             var dataPro = Marshal.AllocHGlobal(Marshal.SizeOf(data));
  86.             var dataSize = Marshal.SizeOf(data);
  87.             var dwReturned = 0;
  88.             try
  89.             {
  90.                 Marshal.StructureToPtr(data, dataPro, true);
  91.                 var hr = _pControl.KsProperty(ref nod.Property, Marshal.SizeOf(nod), dataPro, dataSize, ref dwReturned);
  92.                 if (hr != 0)
  93.                     return dvbResult;
  94.                 dvbResult.Result = 0;
  95.                 return dvbResult;
  96.             }
  97.             finally
  98.             {
  99.                 Marshal.FreeHGlobal(dataPro);
  100.             }
  101.         }
  102.     }
复制代码
  1. /// <summary>
  2.     /// KsProperty 请求类型
  3.     /// </summary>
  4.     [Flags]
  5.     public enum KsPropertyTypeEnum
  6.     {
  7.         /// <summary>
  8.         /// 传递的属性是KSP_NODE类型,其中 NodeId 表示拓扑节点的数字 ID。不要单独设置此标志;相反,将其与该表中的其他标志进行或运算。
  9.         /// </summary>
  10.         KsPropertyTypeTopology = 0x10000000,
  11.         /// <summary>
  12.         /// 检索指定属性项的值。
  13.         /// </summary>
  14.         KsPropertyTypeGet = 0x00000001,
  15.         /// <summary>
  16.         /// 设置指定属性项的值。
  17.         /// </summary>
  18.         KsPropertyTypeSet = 0x00000002,
  19.     }
复制代码
  1. /// <summary>
  2.     /// IKsControl接口提供了控制 KS 过滤器或 KS 引脚的用户模式方法。(参考c语言的Ks.h)
  3.     /// </summary>
  4.     [ComImport, SuppressUnmanagedCodeSecurity,
  5.      Guid("28F54685-06FD-11D2-B27A-00A0C9223196"),
  6.      InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
  7.     public interface IKsControl
  8.     {
  9.         /// <summary>
  10.         /// KsProperty方法设置属性或检索属性信息,以及属性集上可用的任何其他定义的支持操作。
  11.         /// </summary>
  12.         /// <param name="property">指向描述属性和属性请求的请求类型的结构的指针。此结构必须是KSPROPERTY或包含KSPROPERTY结构作为其第一个成员的结构。该成员可以指向的结构示例是KSPROPERTY_VIDEOPROCAMP_S结构。</param>
  13.         /// <param name="propertyLength">Property处缓冲区的大小(以字节为单位)。</param>
  14.         /// <param name="propertyData">指向包含 KSPROPERTY_TYPE_SET、KSPROPERTY_TYPE_UNSERIALIZESET 或 KSPROPERTY_TYPE_UNSERIALIZERAW 操作的数据的缓冲区的指针,或接收所有其他操作的数据的缓冲区空间。</param>
  15.         /// <param name="dataLength">PropertyData中缓冲区的大小(以字节为单位)。</param>
  16.         /// <param name="bytesReturned">指向一个变量的指针,该变量接收KsProperty存储在PropertyData缓冲区中的数据的大小(以字节为单位)。如果没有存储数据,则大小为零。</param>
  17.         /// <returns></returns>
  18.         [PreserveSig]
  19.         int KsProperty(
  20.             [In] ref KsMethod property,
  21.             [In] int propertyLength,
  22.             [In, Out] IntPtr propertyData,
  23.             [In] int dataLength,
  24.             [In, Out] ref int bytesReturned
  25.         );
  26.         /// <summary>
  27.         /// KsMethod方法向 KS 对象发送一个方法,以及方法集上可用的任何其他定义的支持操作。
  28.         /// </summary>
  29.         /// <param name="method">指向描述方法和方法请求的请求类型的KSMETHOD结构的指针。</param>
  30.         /// <param name="methodLength">Method处缓冲区的大小(以字节为单位)。</param>
  31.         /// <param name="methodData">指向包含用于 KSMETHOD_TYPE_SEND 操作的数据和缓冲区空间的缓冲区,或用于接收所有其他操作的数据的缓冲区空间的指针。</param>
  32.         /// <param name="dataLength">MethodData缓冲区的大小(以字节为单位)。</param>
  33.         /// <param name="bytesReturned">指向一个变量的指针,该变量接收KsMethod存储在MethodData缓冲区中的数据的大小(以字节为单位)。</param>
  34.         /// <returns></returns>
  35.         [PreserveSig]
  36.         int KsMethod(
  37.             [In] ref KsMethod method,
  38.             [In] int methodLength,
  39.             [In, Out] IntPtr methodData,
  40.             [In] int dataLength,
  41.             [In, Out] ref int bytesReturned
  42.         );
  43.         /// <summary>
  44.         /// KsEvent方法启用或禁用事件,以及事件集上可用的任何其他定义的支持操作。
  45.         /// </summary>
  46.         /// <param name="method">指向描述事件的KSEVENT结构的指针以启用该事件,为NULL以禁用该事件。</param>
  47.         /// <param name="eventLength">启用事件时事件缓冲区的大小(以字节为单位),禁用事件时为零。</param>
  48.         /// <param name="eventData">指向包含事件数据和接收事件数据的缓冲区空间的KSEVENTDATA结构的指针。</param>
  49.         /// <param name="dataLength">EventData中缓冲区的大小(以字节为单位)。</param>
  50.         /// <param name="bytesReturned">指向一个变量的指针,该变量接收KsEvent存储在EventData缓冲区中的数据的大小(以字节为单位)。</param>
  51.         /// <returns></returns>
  52.         [PreserveSig]
  53.         int KsEvent(
  54.             [In, Optional]  ref KsMethod method,
  55.             [In] int eventLength,
  56.             [In, Out] IntPtr eventData,
  57.             [In] int dataLength,
  58.             [In, Out] ref int bytesReturned
  59.         );
  60.     }
  61.     /// <summary>
  62.     /// 结构指定方法集中的单个内核流方法。
  63.     /// </summary>
  64.     public struct KsMethod
  65.     {
  66.         /// <summary>
  67.         /// 指定标识内核流方法集的 GUID。
  68.         /// </summary>
  69.         public Guid Set;
  70.         /// <summary>
  71.         /// 指定方法集的成员。
  72.         /// </summary>
  73.         public int Id;
  74.         /// <summary>
  75.         ///
  76.         /// </summary>
  77.         public int Flags;
  78.         /// <summary>
  79.         /// 指定请求类型。
  80.         /// </summary>
  81.         /// <param name="set"></param>
  82.         /// <param name="id"></param>
  83.         /// <param name="flags"></param>
  84.         public KsMethod(Guid set, int id, int flags)
  85.         {
  86.             Set = set;
  87.             Id = id;
  88.             Flags = flags;
  89.         }
  90.     }
  91.     /// <summary>
  92.     ///
  93.     /// </summary>
  94.     public struct KspNode
  95.     {
  96.         /// <summary>
  97.         ///
  98.         /// </summary>
  99.         public KsMethod Property;
  100.         /// <summary>
  101.         ///
  102.         /// </summary>
  103.         public Int32 NodeId;
  104.         /// <summary>
  105.         ///
  106.         /// </summary>
  107.         public Int32 Reserved;
  108.     }
复制代码
  1. /// <summary>
  2.     /// UVC扩展接口返回结果
  3.     /// </summary>
  4.     public class DvbResult<T> : DvbResult where T : struct
  5.     {
  6.         /// <summary>
  7.         /// 返回字段结果对象
  8.         /// </summary>
  9.         public T Data { get; set; } = new T();
  10.     }
  11.     /// <summary>
  12.     /// UVC扩展接口返回结果
  13.     /// </summary>
  14.     public class DvbResult
  15.     {
  16.         /// <summary>
  17.         /// 返回结果
  18.         /// </summary>
  19.         public int Result { get; set; } = -1;
  20.     }
复制代码
_pControl.KsProperty(ref nod.Property, Marshal.SizeOf(nod), dataPro, dataSize, ref dwReturned);
(T)Marshal.PtrToStructure(dataPro, typeof(T));
对于返回结果对象类型,经常会出现匹配不上,获取给的字节大小对应不上,导致获取的数据不对。所以最好统一使用byte类型或者byte[]类型获取,然后进一步转化成需要的类型。
例如:
  1. public struct RectangleAreaDvbData
  2.     {
  3.         public RectangleAreaDvbData(byte[] reserve)
  4.         {
  5.             Reserve = reserve;
  6.         }
  7.         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
  8.         public byte[] Reserve;
  9.     }
复制代码
 

来源:https://www.cnblogs.com/log9527blog/archive/2023/03/14/17214022.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具