UVCManager.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  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. if (ctrl.name == "PU_BRIGHTNESS")
  198. Debug.Log($"name:{ctrl.name}, limit: {string.Join(", ", ctrl.limit)}, value: {ctrl.value}, 转插件值后: {ctrl.value / 1000f}");
  199. else if (ctrl.name == "PU_CONTRAST")
  200. Debug.Log($"name:{ctrl.name}, limit: {string.Join(", ", ctrl.limit)}, value: {ctrl.value}, 转插件值后: {ctrl.value / 100f}");
  201. ctrlInfos.Add(ctrl.name,
  202. new UVCCtrlInfo
  203. {
  204. name = ctrl.name,
  205. current = ctrl.value,
  206. min = ctrl.limit != null && ctrl.limit.Length > 0 ? ctrl.limit[0] : 0,
  207. max = ctrl.limit != null && ctrl.limit.Length > 1 ? ctrl.limit[1] : 0,
  208. def = ctrl.limit != null && ctrl.limit.Length > 2 ? ctrl.limit[2] : 0
  209. });
  210. }
  211. }
  212. /**
  213. * 获取支持的 UVC 控制/处理功能的类型列表
  214. */
  215. public List<string> GetCtrls()
  216. {
  217. return new List<string>(ctrlInfos.Keys);
  218. }
  219. /**
  220. * 获取指定 UVC 控制/处理功能的信息
  221. * @param type
  222. * @return UVCCtrlInfo
  223. * @throws ArgumentOutOfRangeException
  224. */
  225. public UVCCtrlInfo GetInfo(string type)
  226. {
  227. if (ctrlInfos.ContainsKey(type))
  228. {
  229. return ctrlInfos.GetValueOrDefault(type, new UVCCtrlInfo());
  230. }
  231. else
  232. {
  233. throw new ArgumentOutOfRangeException($"不支持的控制类型{type:X}");
  234. }
  235. }
  236. public bool ContainsKey(string type)
  237. {
  238. return ctrlInfos.ContainsKey(type);
  239. }
  240. /**
  241. * 获取 UVC 控制/处理功能的设置值
  242. * @param type
  243. * @return 变更后的值
  244. * @throws ArgumentOutOfRangeException
  245. * @throws Exception
  246. */
  247. public Int32 GetValue(string type)
  248. {
  249. if (ctrlInfos.ContainsKey(type))
  250. {
  251. var r = ctrlInfos.GetValueOrDefault(type, new UVCCtrlInfo());
  252. if (r.name != null)
  253. {
  254. return r.current;
  255. }
  256. else
  257. {
  258. throw new Exception($"获取控制值失败,type={type},err={r}");
  259. }
  260. }
  261. else
  262. {
  263. throw new ArgumentOutOfRangeException($"不支持的控制类型{type:X}");
  264. }
  265. }
  266. /**
  267. * 修改 UVC 控制/处理功能的设置
  268. * @param type
  269. * @param value
  270. * @return 变更后的值
  271. * @throws ArgumentOutOfRangeException
  272. * @throws Exception
  273. */
  274. public Int32 SetValue(string type, Int32 value)
  275. {
  276. if (ctrlInfos.ContainsKey(type))
  277. {
  278. var r = uvcInterface.SetCtrlValue(type, value);
  279. if (r == 0)
  280. {
  281. UpdateCtrls(); // 同步刷列表
  282. var info = ctrlInfos.GetValueOrDefault(type, new UVCCtrlInfo());
  283. info.current = value;
  284. ctrlInfos[type] = info;
  285. return value;
  286. }
  287. else
  288. {
  289. Debug.LogError($"设置控制值失败,type={type},err={r}");
  290. }
  291. }
  292. else
  293. {
  294. Debug.LogError($"不支持的控制类型{type:X}");
  295. }
  296. return 0;
  297. }
  298. public override string ToString()
  299. {
  300. return $"{base.ToString()}({currentWidth}x{currentHeight},activeId={activeId},IsPreviewing={IsPreviewing})";
  301. }
  302. } // CameraInfo
  303. /**
  304. * 获取映像中的 UVC 设备映射
  305. */
  306. private CameraInfo cameraInfo;
  307. /// <summary>
  308. /// 开始事件
  309. /// </summary>
  310. [HideInInspector]
  311. public UnityEvent<CameraInfo> startUVCManager;
  312. /// <summary>
  313. /// 更新事件
  314. /// </summary>
  315. [HideInInspector]
  316. public UnityEvent<bool> updateUVCManager;
  317. private bool bInit = false;
  318. private void Awake()
  319. {
  320. // _interface = GetComponent<UVCInterface>();
  321. #if UNITY_IOS
  322. _interface = gameObject.AddComponent<UVCInterface_IOS>();
  323. #elif UNITY_ANDROID
  324. _interface = gameObject.AddComponent<UVCInterface_Android>();
  325. #else
  326. Debug.LogError("Unsupported platform!");
  327. #endif
  328. _interface.systemCameraPermissionHandle += () =>
  329. {
  330. //授权系统相机之后,初始化红外相机
  331. initUVCManagerCamera();
  332. };
  333. }
  334. private void Start()
  335. {
  336. //initUVCManagerCamera();
  337. }
  338. /// <summary>
  339. /// 初始化相机系统
  340. /// </summary>
  341. public void initUVCManagerCamera()
  342. {
  343. _interface.cameraTextureHandle += () =>
  344. {
  345. Debug.Log("cameraTextureHandle");
  346. if (_interface.CameraTexture == null)
  347. {
  348. Debug.LogError("[Error] CameraTexture is NULL!");
  349. return;
  350. }
  351. var info = GetCamera();
  352. if (info == null)
  353. {
  354. Debug.LogError("[Error] GetCamera() returned NULL!");
  355. return;
  356. }
  357. //bChange反馈是否变化宽高
  358. bool bChange = info.SetSize(_interface.CameraTexture.width, _interface.CameraTexture.height);
  359. info.previewTexture = _interface.CameraTexture;
  360. info.activeId = 1;
  361. if (bInit)
  362. {
  363. //之后的触发的重新创建纹理更新
  364. updateUVCManager?.Invoke(bChange);
  365. }
  366. else
  367. {
  368. /**
  369. * 第一次更新触发初始化
  370. */
  371. info.UpdateCtrls();//获取摄像机参数
  372. info.UpdateResolution();//获取摄像机分辨率
  373. startUVCManager?.Invoke(info);
  374. // StartCoroutine(DelayGetInfo(info));
  375. }
  376. bInit = true;
  377. };
  378. //初始化相机,连接设备时候自动开启渲染
  379. _interface.InitCamera(DefaultWidth, DefaultHeight);
  380. }
  381. /// <summary>
  382. /// 延迟一下获取操作参数
  383. /// </summary>
  384. /// <param name="info"></param>
  385. /// <returns></returns>
  386. //IEnumerator DelayGetInfo(CameraInfo info)
  387. //{
  388. // yield return new WaitForSecondsRealtime(0.5f);
  389. //}
  390. /// <summary>
  391. /// 开启渲染
  392. /// </summary>
  393. public void onStartPreview()
  394. {
  395. _interface.OpenCamera();
  396. }
  397. /// <summary>
  398. /// 停止渲染
  399. /// </summary>
  400. public void onStopPreview()
  401. {
  402. _interface.CloseCamera();
  403. //重置cameraInfo的参数
  404. var info = GetCamera();
  405. info.SetSize(0, 0);
  406. info.previewTexture = null;
  407. info.activeId = 0;
  408. }
  409. /**
  410. * 获取与指定的 UVC 识别字符串对应的 CameraInfo
  411. * @param device
  412. * @return 如果已注册,则返回 CameraInfo;如果未注册,则返回 New CameraInfo
  413. */
  414. /*Nullable*/
  415. private CameraInfo GetCamera()
  416. {
  417. if (cameraInfo == null)
  418. cameraInfo = new CameraInfo(_interface);
  419. return cameraInfo;
  420. }
  421. }
  422. }