UVCManager.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  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. using UnityEngine.Events;
  15. #if UNITY_ANDROID && UNITY_2018_3_OR_NEWER
  16. using UnityEngine.Android;
  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. {
  109. bChange = true;
  110. currentWidth = width;
  111. currentHeight = height;
  112. }
  113. Debug.Log("CameraInfo设置SetSize,大小变化:" + bChange + ",Size:[" + width + "," + height + "]");
  114. return bChange;
  115. }
  116. /**
  117. * 当前默认分辨率
  118. */
  119. public Vector2 CurrentCalibrationResolution
  120. {
  121. get { return CalibrationResolution; }
  122. }
  123. /**
  124. * 当前默认校准时候高分辨率
  125. */
  126. public Vector2 CurrentHighResolution
  127. {
  128. get { return HighResolution; }
  129. }
  130. /**
  131. * 当前默认最低分辨率
  132. */
  133. public Vector2 CurrentLowResolution
  134. {
  135. get { return LowResolution; }
  136. }
  137. /**
  138. * 修改相机的分辨率,相机分辨率修改成功回调后才修改 本地分辨率
  139. * @param width
  140. * @param height
  141. */
  142. internal bool SetCameraSize(Int32 width, Int32 height)
  143. {
  144. bool bChange = false;
  145. if (width != currentWidth || height != currentHeight)
  146. {
  147. bChange = true;
  148. uvcInterface?.ChangeCameraInfo(width, height);
  149. }
  150. return bChange;
  151. }
  152. /**
  153. * 更新支持的分辨率
  154. */
  155. public void UpdateResolution()
  156. {
  157. string[] resolutions = uvcInterface.GetSupportedResolutions();
  158. resolutionInfos.Clear();
  159. //resolutions 数组是从大到小
  160. for (int i = 0; i < resolutions.Length; i++)
  161. {
  162. string resolution = resolutions[i];
  163. string[] res = resolution.ToString().Split('x');
  164. resolutionInfos.Add(resolution, new Vector2(int.Parse(res[0]), int.Parse(res[1])));
  165. }
  166. }
  167. /**
  168. * 获取分辨率的key: 1280 * 720
  169. */
  170. public List<string> GetResolutionsStrs()
  171. {
  172. return new List<string>(resolutionInfos.Keys);
  173. }
  174. /**
  175. * 获取分辨率的values:Vector2(1280,720)
  176. */
  177. public List<Vector2> GetResolutionsVec2s()
  178. {
  179. return new List<Vector2>(resolutionInfos.Values);
  180. }
  181. /**
  182. * 是否存在分辨率
  183. */
  184. public bool ContainsResulutionKey(string type)
  185. {
  186. return resolutionInfos.ContainsKey(type);
  187. }
  188. /**
  189. * 更新支持的 UVC 控制/处理功能信息
  190. */
  191. public void UpdateCtrls()
  192. {
  193. uvcInterface.GetUvcCtrlList();
  194. ctrlInfos.Clear();
  195. foreach (UVCCtrl ctrl in uvcInterface.UVCCtrls)
  196. {
  197. // Debug.Log($"name:{ctrl.name}, isAuto: {ctrl.isAuto}, isEnable: {ctrl.isEnable}, limit: {string.Join(", ", ctrl.limit)}, value: {ctrl.value}");
  198. ctrlInfos.Add(ctrl.name,
  199. new UVCCtrlInfo
  200. {
  201. name = ctrl.name,
  202. current = ctrl.value,
  203. min = ctrl.limit != null && ctrl.limit.Length > 0 ? ctrl.limit[0] : 0,
  204. max = ctrl.limit != null && ctrl.limit.Length > 1 ? ctrl.limit[1] : 0,
  205. def = ctrl.limit != null && ctrl.limit.Length > 2 ? ctrl.limit[2] : 0
  206. });
  207. }
  208. }
  209. /**
  210. * 获取支持的 UVC 控制/处理功能的类型列表
  211. */
  212. public List<string> GetCtrls()
  213. {
  214. return new List<string>(ctrlInfos.Keys);
  215. }
  216. /**
  217. * 获取指定 UVC 控制/处理功能的信息
  218. * @param type
  219. * @return UVCCtrlInfo
  220. * @throws ArgumentOutOfRangeException
  221. */
  222. public UVCCtrlInfo GetInfo(string type)
  223. {
  224. if (ctrlInfos.ContainsKey(type))
  225. {
  226. return ctrlInfos.GetValueOrDefault(type, new UVCCtrlInfo());
  227. }
  228. else
  229. {
  230. throw new ArgumentOutOfRangeException($"不支持的控制类型{type:X}");
  231. }
  232. }
  233. public bool ContainsKey(string type)
  234. {
  235. return ctrlInfos.ContainsKey(type);
  236. }
  237. /**
  238. * 获取 UVC 控制/处理功能的设置值
  239. * @param type
  240. * @return 变更后的值
  241. * @throws ArgumentOutOfRangeException
  242. * @throws Exception
  243. */
  244. public Int32 GetValue(string type)
  245. {
  246. if (ctrlInfos.ContainsKey(type))
  247. {
  248. var r = ctrlInfos.GetValueOrDefault(type, new UVCCtrlInfo());
  249. if (r.name != null)
  250. {
  251. return r.current;
  252. }
  253. else
  254. {
  255. throw new Exception($"获取控制值失败,type={type},err={r}");
  256. }
  257. }
  258. else
  259. {
  260. throw new ArgumentOutOfRangeException($"不支持的控制类型{type:X}");
  261. }
  262. }
  263. /**
  264. * 修改 UVC 控制/处理功能的设置
  265. * @param type
  266. * @param value
  267. * @return 变更后的值
  268. * @throws ArgumentOutOfRangeException
  269. * @throws Exception
  270. */
  271. public Int32 SetValue(string type, Int32 value)
  272. {
  273. if (ctrlInfos.ContainsKey(type))
  274. {
  275. var r = uvcInterface.SetCtrlValue(type, value);
  276. if (r == 0)
  277. {
  278. UpdateCtrls(); // 同步刷列表
  279. var info = ctrlInfos.GetValueOrDefault(type, new UVCCtrlInfo());
  280. info.current = value;
  281. ctrlInfos[type] = info;
  282. return value;
  283. }
  284. else
  285. {
  286. Debug.LogError($"设置控制值失败,type={type},err={r}");
  287. }
  288. }
  289. else
  290. {
  291. Debug.LogError($"不支持的控制类型{type:X}");
  292. }
  293. return 0;
  294. }
  295. public override string ToString()
  296. {
  297. return $"{base.ToString()}({currentWidth}x{currentHeight},activeId={activeId},IsPreviewing={IsPreviewing})";
  298. }
  299. } // CameraInfo
  300. /**
  301. * 获取映像中的 UVC 设备映射
  302. */
  303. private CameraInfo cameraInfo;
  304. /// <summary>
  305. /// 开始事件
  306. /// </summary>
  307. [HideInInspector]
  308. public UnityEvent<CameraInfo> startUVCManager;
  309. /// <summary>
  310. /// 更新事件
  311. /// </summary>
  312. [HideInInspector]
  313. public UnityEvent<bool> updateUVCManager;
  314. private bool bInit = false;
  315. private void Awake()
  316. {
  317. _interface = GetComponent<UVCInterface>();
  318. _interface.systemCameraPermissionHandle += () =>
  319. {
  320. //授权系统相机之后,初始化红外相机
  321. initUVCManagerCamera();
  322. };
  323. }
  324. private void Start()
  325. {
  326. //initUVCManagerCamera();
  327. }
  328. /// <summary>
  329. /// 初始化相机系统
  330. /// </summary>
  331. public void initUVCManagerCamera()
  332. {
  333. //初始化相机,连接设备时候自动开启渲染
  334. _interface.InitCamera(DefaultWidth, DefaultHeight);
  335. _interface.cameraTextureHandle += () =>
  336. {
  337. var info = GetCamera();
  338. //bChange反馈是否变化宽高
  339. bool bChange = info.SetSize(_interface.CameraTexture.width, _interface.CameraTexture.height);
  340. info.previewTexture = _interface.CameraTexture;
  341. info.activeId = 1;
  342. if (bInit)
  343. {
  344. //之后的触发的重新创建纹理更新
  345. updateUVCManager?.Invoke(bChange);
  346. }
  347. else
  348. {
  349. /**
  350. * 第一次更新触发初始化
  351. */
  352. info.UpdateCtrls();//获取摄像机参数
  353. info.UpdateResolution();//获取摄像机分辨率
  354. startUVCManager?.Invoke(info);
  355. // StartCoroutine(DelayGetInfo(info));
  356. }
  357. bInit = true;
  358. };
  359. }
  360. /// <summary>
  361. /// 延迟一下获取操作参数
  362. /// </summary>
  363. /// <param name="info"></param>
  364. /// <returns></returns>
  365. //IEnumerator DelayGetInfo(CameraInfo info)
  366. //{
  367. // yield return new WaitForSecondsRealtime(0.5f);
  368. //}
  369. /// <summary>
  370. /// 开启渲染
  371. /// </summary>
  372. public void onStartPreview()
  373. {
  374. _interface.OpenCamera();
  375. }
  376. /// <summary>
  377. /// 停止渲染
  378. /// </summary>
  379. public void onStopPreview()
  380. {
  381. _interface.CloseCamera();
  382. //重置cameraInfo的参数
  383. var info = GetCamera();
  384. info.SetSize(0, 0);
  385. info.previewTexture = null;
  386. info.activeId = 0;
  387. }
  388. /**
  389. * 获取与指定的 UVC 识别字符串对应的 CameraInfo
  390. * @param device
  391. * @return 如果已注册,则返回 CameraInfo;如果未注册,则返回 New CameraInfo
  392. */
  393. /*Nullable*/
  394. private CameraInfo GetCamera()
  395. {
  396. if (cameraInfo == null)
  397. cameraInfo = new CameraInfo(_interface);
  398. return cameraInfo;
  399. }
  400. }
  401. }