UVCManager.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. #define ENABLE_LOG
  2. #define DEBUG
  3. /*
  4. * Copyright (c) 2014 - 2022 t_saki@serenegiant.com
  5. */
  6. using AOT;
  7. using System;
  8. using System.Collections;
  9. using System.Collections.Generic;
  10. using System.Runtime.CompilerServices;
  11. using System.Runtime.InteropServices;
  12. using System.Threading;
  13. using UnityEngine;
  14. #if UNITY_ANDROID && UNITY_2018_3_OR_NEWER
  15. using UnityEngine.Android;
  16. using UnityEngine.Events;
  17. #endif
  18. namespace SLAMUVC
  19. {
  20. [RequireComponent(typeof(UVCInterface))]
  21. public class UVCManager : MonoBehaviour
  22. {
  23. private const string TAG = "UVCManager#";
  24. //--------------------------------------------------------------------------------
  25. public Int32 DefaultWidth = 1280;
  26. public Int32 DefaultHeight = 720;
  27. protected UVCInterface _interface;
  28. /**
  29. * 保持正在使用的相机信息
  30. */
  31. public class CameraInfo
  32. {
  33. //internal readonly UVCDevice device;
  34. internal UVCInterface uvcInterface;
  35. internal Texture previewTexture;
  36. internal int frameType;
  37. internal volatile Int32 activeId;
  38. private Int32 currentWidth;
  39. private Int32 currentHeight;
  40. //校准时候使用的分辨率
  41. Vector2 CalibrationResolution = new Vector2(1280, 720);//"1280x720";
  42. //识别的最高分辨率
  43. Vector2 HighResolution = new Vector2(320, 240);//"320x240";
  44. //识别的最低分辨率
  45. Vector2 LowResolution = new Vector2(160, 120);// "160x120";
  46. //摄像机参数
  47. private Dictionary<string, UVCCtrlInfo> ctrlInfos = new Dictionary<string, UVCCtrlInfo>();
  48. //当前摄像机分辨率
  49. private Dictionary<string, Vector2> resolutionInfos = new Dictionary<string, Vector2>();
  50. //PC测试用
  51. internal CameraInfo(Texture texture)
  52. {
  53. // this.device = null;
  54. activeId = 1;
  55. previewTexture = texture;
  56. SetSize(texture.width, texture.height);
  57. }
  58. internal CameraInfo(UVCInterface _uvcInterface)
  59. {
  60. this.uvcInterface = _uvcInterface;
  61. }
  62. /**
  63. * 是否正在获取图像
  64. */
  65. public bool IsPreviewing
  66. {
  67. get { return (activeId != 0) && (previewTexture != null); }
  68. }
  69. /**
  70. * 当前分辨率(宽度)
  71. * 如果不在预览中则为0
  72. */
  73. public Int32 CurrentWidth
  74. {
  75. get { return currentWidth; }
  76. }
  77. /**
  78. * 当前分辨率(高度)
  79. * 如果不在预览中则为0
  80. */
  81. public Int32 CurrentHeight
  82. {
  83. get { return currentHeight; }
  84. }
  85. /**
  86. * 返回一个尺寸
  87. */
  88. public Vector2 Size => new Vector2(currentWidth, currentHeight);
  89. public Vector2Int IndexToCoord(int i)
  90. {
  91. var y = i / currentWidth;
  92. var x = i % currentWidth;
  93. return new Vector2Int(x, y);
  94. }
  95. public int CoordToIndex(int x, int y)
  96. {
  97. return y * currentWidth + x;
  98. }
  99. /**
  100. * 修改当前分辨率
  101. * @param width
  102. * @param height
  103. */
  104. internal bool SetSize(Int32 width, Int32 height)
  105. {
  106. bool bChange = false;
  107. if (width != currentWidth || height != currentHeight) {
  108. bChange = true;
  109. currentWidth = width;
  110. currentHeight = height;
  111. }
  112. Debug.Log("CameraInfo设置SetSize,大小变化:" + bChange + ",Size:[" + width + "," + height + "]");
  113. return bChange;
  114. }
  115. /**
  116. * 当前默认分辨率
  117. */
  118. public Vector2 CurrentCalibrationResolution
  119. {
  120. get { return CalibrationResolution; }
  121. }
  122. /**
  123. * 当前默认校准时候高分辨率
  124. */
  125. public Vector2 CurrentHighResolution
  126. {
  127. get { return HighResolution; }
  128. }
  129. /**
  130. * 当前默认最低分辨率
  131. */
  132. public Vector2 CurrentLowResolution
  133. {
  134. get { return LowResolution; }
  135. }
  136. /**
  137. * 修改相机的分辨率,相机分辨率修改成功回调后才修改 本地分辨率
  138. * @param width
  139. * @param height
  140. */
  141. internal bool SetCameraSize(Int32 width, Int32 height) {
  142. bool bChange = false;
  143. if (width != currentWidth || height != currentHeight)
  144. {
  145. bChange = true;
  146. uvcInterface.ChangeCameraInfo(width, height);
  147. }
  148. return bChange;
  149. }
  150. /**
  151. * 更新支持的分辨率
  152. */
  153. public void UpdateResolution()
  154. {
  155. string[] resolutions = uvcInterface.GetSupportedResolutions();
  156. resolutionInfos.Clear();
  157. //resolutions 数组是从大到小
  158. for (int i = 0; i < resolutions.Length; i++)
  159. {
  160. string resolution = resolutions[i];
  161. string[] res = resolution.ToString().Split('x');
  162. resolutionInfos.Add(resolution, new Vector2(int.Parse(res[0]), int.Parse(res[1])));
  163. }
  164. }
  165. /**
  166. * 获取分辨率的key: 1280 * 720
  167. */
  168. public List<string> GetResolutionsStrs()
  169. {
  170. return new List<string>(resolutionInfos.Keys);
  171. }
  172. /**
  173. * 获取分辨率的values:Vector2(1280,720)
  174. */
  175. public List<Vector2> GetResolutionsVec2s()
  176. {
  177. return new List<Vector2>(resolutionInfos.Values);
  178. }
  179. /**
  180. * 是否存在分辨率
  181. */
  182. public bool ContainsResulutionKey(string type)
  183. {
  184. return resolutionInfos.ContainsKey(type);
  185. }
  186. /**
  187. * 更新支持的 UVC 控制/处理功能信息
  188. */
  189. public void UpdateCtrls()
  190. {
  191. uvcInterface.GetUvcCtrlList();
  192. ctrlInfos.Clear();
  193. foreach (UVCCtrl ctrl in uvcInterface.UVCCtrls)
  194. {
  195. Debug.Log($"name:{ctrl.name}, isAuto: {ctrl.isAuto}, isEnable: {ctrl.isEnable}, limit: {string.Join(", ", ctrl.limit)}, value: {ctrl.value}");
  196. ctrlInfos.Add(ctrl.name,
  197. new UVCCtrlInfo
  198. {
  199. name = ctrl.name,
  200. current = ctrl.value,
  201. min = ctrl.limit != null && ctrl.limit.Length > 0 ? ctrl.limit[0] : 0,
  202. max = ctrl.limit != null && ctrl.limit.Length > 1 ? ctrl.limit[1] : 0,
  203. def = ctrl.limit != null && ctrl.limit.Length > 2 ? ctrl.limit[2] : 0
  204. });
  205. }
  206. }
  207. /**
  208. * 获取支持的 UVC 控制/处理功能的类型列表
  209. */
  210. public List<string> GetCtrls()
  211. {
  212. return new List<string>(ctrlInfos.Keys);
  213. }
  214. /**
  215. * 获取指定 UVC 控制/处理功能的信息
  216. * @param type
  217. * @return UVCCtrlInfo
  218. * @throws ArgumentOutOfRangeException
  219. */
  220. public UVCCtrlInfo GetInfo(string type)
  221. {
  222. if (ctrlInfos.ContainsKey(type))
  223. {
  224. return ctrlInfos.GetValueOrDefault(type, new UVCCtrlInfo());
  225. }
  226. else
  227. {
  228. throw new ArgumentOutOfRangeException($"不支持的控制类型{type:X}");
  229. }
  230. }
  231. public bool ContainsKey(string type)
  232. {
  233. return ctrlInfos.ContainsKey(type);
  234. }
  235. /**
  236. * 获取 UVC 控制/处理功能的设置值
  237. * @param type
  238. * @return 变更后的值
  239. * @throws ArgumentOutOfRangeException
  240. * @throws Exception
  241. */
  242. public Int32 GetValue(string type)
  243. {
  244. if (ctrlInfos.ContainsKey(type))
  245. {
  246. var r = ctrlInfos.GetValueOrDefault(type, new UVCCtrlInfo());
  247. if (r.name != null)
  248. {
  249. return r.current;
  250. }
  251. else
  252. {
  253. throw new Exception($"获取控制值失败,type={type},err={r}");
  254. }
  255. }
  256. else
  257. {
  258. throw new ArgumentOutOfRangeException($"不支持的控制类型{type:X}");
  259. }
  260. }
  261. /**
  262. * 修改 UVC 控制/处理功能的设置
  263. * @param type
  264. * @param value
  265. * @return 变更后的值
  266. * @throws ArgumentOutOfRangeException
  267. * @throws Exception
  268. */
  269. public Int32 SetValue(string type, Int32 value)
  270. {
  271. if (ctrlInfos.ContainsKey(type))
  272. {
  273. var r = uvcInterface.SetCtrlValue(type, value);
  274. if (r == 0)
  275. {
  276. UpdateCtrls(); // 同步刷列表
  277. var info = ctrlInfos.GetValueOrDefault(type, new UVCCtrlInfo());
  278. info.current = value;
  279. ctrlInfos[type] = info;
  280. return value;
  281. }
  282. else
  283. {
  284. Debug.LogError($"设置控制值失败,type={type},err={r}");
  285. }
  286. }
  287. else
  288. {
  289. Debug.LogError($"不支持的控制类型{type:X}");
  290. }
  291. return 0;
  292. }
  293. public override string ToString()
  294. {
  295. return $"{base.ToString()}({currentWidth}x{currentHeight},activeId={activeId},IsPreviewing={IsPreviewing})";
  296. }
  297. } // CameraInfo
  298. /**
  299. * 获取映像中的 UVC 设备映射
  300. */
  301. private CameraInfo cameraInfo;
  302. /// <summary>
  303. /// 开始事件
  304. /// </summary>
  305. [HideInInspector]
  306. public UnityEvent<CameraInfo> startUVCManager;
  307. /// <summary>
  308. /// 更新事件
  309. /// </summary>
  310. [HideInInspector]
  311. public UnityEvent<bool> updateUVCManager;
  312. private bool bInit = false;
  313. private void Awake()
  314. {
  315. _interface = GetComponent<UVCInterface>();
  316. _interface.systemCameraPermissionHandle += () =>
  317. {
  318. //授权系统相机之后,初始化红外相机
  319. initUVCManagerCamera();
  320. };
  321. }
  322. private void Start()
  323. {
  324. //initUVCManagerCamera();
  325. }
  326. /// <summary>
  327. /// 初始化相机系统
  328. /// </summary>
  329. public void initUVCManagerCamera()
  330. {
  331. //初始化相机,连接设备时候自动开启渲染
  332. _interface.InitCamera(DefaultWidth, DefaultHeight);
  333. _interface.cameraTextureHandle += () =>
  334. {
  335. var info = GetCamera();
  336. //bChange反馈是否变化宽高
  337. bool bChange = info.SetSize(_interface.CameraTexture.width, _interface.CameraTexture.height);
  338. info.previewTexture = _interface.CameraTexture;
  339. info.activeId = 1;
  340. if (bInit)
  341. {
  342. //之后的触发的重新创建纹理更新
  343. updateUVCManager?.Invoke(bChange);
  344. }
  345. else {
  346. /**
  347. * 第一次更新触发初始化
  348. */
  349. info.UpdateCtrls();//获取摄像机参数
  350. info.UpdateResolution();//获取摄像机分辨率
  351. startUVCManager?.Invoke(info);
  352. }
  353. bInit = true;
  354. };
  355. }
  356. /// <summary>
  357. /// 开启渲染
  358. /// </summary>
  359. public void onStartPreview()
  360. {
  361. _interface.OpenCamera();
  362. }
  363. /// <summary>
  364. /// 停止渲染
  365. /// </summary>
  366. public void onStopPreview()
  367. {
  368. _interface.CloseCamera();
  369. //重置cameraInfo的参数
  370. var info = GetCamera();
  371. info.SetSize(0, 0);
  372. info.previewTexture = null;
  373. info.activeId = 0;
  374. }
  375. /**
  376. * 获取与指定的 UVC 识别字符串对应的 CameraInfo
  377. * @param device
  378. * @return 如果已注册,则返回 CameraInfo;如果未注册,则返回 New CameraInfo
  379. */
  380. /*Nullable*/
  381. private CameraInfo GetCamera()
  382. {
  383. if(cameraInfo ==null)
  384. cameraInfo = new CameraInfo(_interface);
  385. return cameraInfo;
  386. }
  387. }
  388. }