UVCInterface.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. using UnityEngine;
  2. using System;
  3. using System.Collections;
  4. using System.Runtime.InteropServices;
  5. using SLAMUVC;
  6. using UnityEngine.UI;
  7. using System.Collections.Generic;
  8. using AOT;
  9. using System.Threading;
  10. using UnityEngine.Events;
  11. using UnityEngine.Android;
  12. namespace SLAMUVC
  13. {
  14. [StructLayout(LayoutKind.Sequential, Pack = 4)]
  15. public struct UVCCtrlInfo
  16. {
  17. public string name;
  18. public Int32 current;
  19. public Int32 min;
  20. public Int32 max;
  21. public Int32 def;
  22. public override string ToString()
  23. {
  24. return $"{base.ToString()}(name={name},min={min},max={max},def={def},current={current})";
  25. }
  26. }
  27. [System.Serializable]
  28. public class UVCCtrl
  29. {
  30. public string name;
  31. public bool isAuto;
  32. public bool isEnable;
  33. public int[] limit;
  34. public int value;
  35. }
  36. [System.Serializable]
  37. public class UVCCtrlWrapper
  38. {
  39. public UVCCtrl[] uvcCtrls;
  40. }
  41. public enum CameraFormat
  42. {
  43. MJPEG,
  44. YUV,
  45. }
  46. public enum CameraMirror
  47. {
  48. NONE,
  49. HORIZONTAL,//水平翻转
  50. VERTICAL//垂直翻转
  51. }
  52. public enum UVCCameraPixelFormat
  53. {
  54. PIXEL_FORMAT_RAW,
  55. PIXEL_FORMAT_YUV,
  56. PIXEL_FORMAT_NV12, // one format of YUV420SemiPlanar
  57. PIXEL_FORMAT_NV21, // one format of YUV420SemiPlanar
  58. PIXEL_FORMAT_RGB,
  59. PIXEL_FORMAT_RGB565,
  60. PIXEL_FORMAT_RGBX
  61. }
  62. //UVC的管理类
  63. public class UVCInterface : MonoBehaviour
  64. {
  65. private const string UVC_MANAGER = "com.slambb.myuvc.MyUVCManager";
  66. //java对象
  67. private AndroidJavaObject uvcManagerObj = null;
  68. CameraFormat mCameraFormat = CameraFormat.MJPEG;
  69. CameraMirror mCameraMirror = CameraMirror.VERTICAL;//默认垂直
  70. int Width = 1280;
  71. int Height = 720;
  72. Texture2D _cameraTexture;
  73. public Texture2D CameraTexture => _cameraTexture;
  74. private UVCCtrl[] uvcCtrls;
  75. public UVCCtrl[] UVCCtrls => uvcCtrls;
  76. private SynchronizationContext mainContext;
  77. /// <summary>
  78. /// 初始化相机权限成功
  79. /// </summary>
  80. public CameraPermissionHandle systemCameraPermissionHandle;
  81. public delegate void CameraPermissionHandle();
  82. /// <summary>
  83. /// 纹理更新事件
  84. /// </summary>
  85. public CameraTextureHandle cameraTextureHandle;
  86. public delegate void CameraTextureHandle();
  87. private static readonly string ActivityClassName = "com.slambb.myuvc.UsbPermissionActivity";
  88. //public void RequestUsbPermission()
  89. //{
  90. // using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
  91. // {
  92. // AndroidJavaObject activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
  93. // AndroidJavaClass usbPermissionActivity = new AndroidJavaClass(ActivityClassName);
  94. // // Start UsbPermissionActivity
  95. // activity.Call("startActivity", usbPermissionActivity.CallStatic<AndroidJavaObject>("newIntent", activity));
  96. // }
  97. //}
  98. void Awake()
  99. {
  100. try
  101. {
  102. // 创建 uvcManagerObj 对象
  103. uvcManagerObj = new AndroidJavaObject(UVC_MANAGER);
  104. }
  105. catch (Exception e)
  106. {
  107. Debug.LogError("UVC_MANAGER Exception: " + e.Message);
  108. }
  109. //RequestUsbPermission();
  110. }
  111. void Start()
  112. {
  113. OpenCameraPermisson();
  114. }
  115. private void OnDestroy()
  116. {
  117. Remove(this);
  118. uvcManagerObj.Call("clearCameraHelper");
  119. }
  120. /// <summary>
  121. /// 创建一个纹理id到插件
  122. /// </summary>
  123. private void CreateTextureAndPassToPlugin()
  124. {
  125. // 销毁纹理
  126. if (_cameraTexture != null)
  127. {
  128. Destroy(_cameraTexture);
  129. _cameraTexture = null;
  130. }
  131. // Create a texture
  132. Texture2D tex = new Texture2D(Width, Height, TextureFormat.ARGB32, false);
  133. // 设置点过滤,以便我们可以清楚地看到像素
  134. tex.filterMode = FilterMode.Point;
  135. // 调用Apply(),使其实际上传到GPU
  136. tex.Apply();
  137. _cameraTexture = tex;
  138. //将纹理指针传递给插件
  139. SetTexture(tex.GetNativeTexturePtr(), tex.width, tex.height);
  140. cameraTextureHandle?.Invoke();
  141. }
  142. //private IEnumerator CallPluginAtEndOfFrames()
  143. //{
  144. // while (true)
  145. // {
  146. // //等待所有帧渲染完成
  147. // yield return new WaitForEndOfFrame();
  148. // //发出具有任意整数标识符的插件事件。
  149. // //该插件可以区分不同的
  150. // //它需要根据这个ID做的事情。
  151. // //对于我们的简单插件,我们在这里传递哪个ID并不重要。
  152. // if(GetIsPreviewing()) GL.IssuePluginEvent(GetRenderEventFunc(), 1);
  153. // }
  154. //}
  155. /// <summary>
  156. /// 更新纹理
  157. /// </summary>
  158. /// <param name="width"></param>
  159. /// <param name="height"></param>
  160. /// <param name="bUpdate"></param>
  161. public void OnTextureUpdate(int width, int height, bool bUpdate)
  162. {
  163. mainContext.Post(__ =>
  164. {
  165. if (bUpdate)
  166. {
  167. Debug.Log("创建新纹理:size=[" + width + "," + height + "]");
  168. Width = width;
  169. Height = height;
  170. CreateTextureAndPassToPlugin();
  171. }
  172. else
  173. {
  174. GL.IssuePluginEvent(GetRenderEventFunc(), 1);
  175. }
  176. }, null);
  177. }
  178. public bool GetIsPreviewing()
  179. {
  180. if (uvcManagerObj != null)
  181. {
  182. if (uvcManagerObj.Call<int>("GetIsPreviewing") == 1)
  183. {
  184. return true;
  185. }
  186. }
  187. return false;
  188. }
  189. /// <summary>
  190. /// 初始化相机和对应的操作,初始化后会自动打开相机
  191. /// </summary>
  192. /// <param name="width"></param>
  193. /// <param name="height"></param>
  194. public void InitCamera(int width, int height)
  195. {
  196. Width = width;
  197. Height = height;
  198. uvcManagerObj.Call("initCameraHelper", Width, Height, mCameraFormat.ToString(), mCameraMirror.ToString());
  199. //主线程
  200. mainContext = SynchronizationContext.Current;
  201. //注册c回调
  202. Add(this);
  203. //mainContext.Post(__ =>
  204. //{
  205. // //CreateTextureAndPassToPlugin();
  206. //}, null);
  207. //StartCoroutine("CallPluginAtEndOfFrames");
  208. }
  209. public void OpenCamera()
  210. {
  211. uvcManagerObj.Call("OpenCamera");
  212. }
  213. public void CloseCamera()
  214. {
  215. uvcManagerObj.Call("CloseCamera");
  216. }
  217. public void ChangeCameraInfo(int width, int height)
  218. {
  219. uvcManagerObj.Call("ChangeCameraInfo", width, height, mCameraFormat.ToString());
  220. }
  221. public string[] GetSupportedResolutions()
  222. {
  223. if (uvcManagerObj != null)
  224. {
  225. var objPtr = uvcManagerObj.Call<AndroidJavaObject>("GetSupportedResolutions").GetRawObject();
  226. if (objPtr != IntPtr.Zero)
  227. return AndroidJNIHelper.ConvertFromJNIArray<string[]>(objPtr);
  228. }
  229. return null;
  230. }
  231. /// <summary>
  232. /// 水平翻转
  233. /// </summary>
  234. public void FlipHorizontally()
  235. {
  236. uvcManagerObj.Call("FlipHorizontally");
  237. }
  238. /// <summary>
  239. /// 垂直翻转
  240. /// </summary>
  241. public void FlipVertically()
  242. {
  243. uvcManagerObj.Call("FlipVertically");
  244. }
  245. public void resetControlParams()
  246. {
  247. uvcManagerObj.Call("resetControlParams");
  248. }
  249. public void GetUvcCtrlList()
  250. {
  251. if (uvcManagerObj != null)
  252. {
  253. string json = uvcManagerObj.Call<string>("GetUvcCtrlList");
  254. UVCCtrlWrapper wrapper = JsonUtility.FromJson<UVCCtrlWrapper>("{\"uvcCtrls\":" + json + "}");
  255. if (wrapper != null && wrapper.uvcCtrls != null)
  256. {
  257. //赋值
  258. uvcCtrls = wrapper.uvcCtrls;
  259. //foreach (UVCCtrl ctrl in wrapper.uvcCtrls)
  260. //{
  261. // Debug.Log($"name:{ctrl.name}, isAuto: {ctrl.isAuto}, isEnable: {ctrl.isEnable}, limit: {string.Join(", ", ctrl.limit)}, value: {ctrl.value}");
  262. //}
  263. }
  264. else
  265. {
  266. Debug.LogError("Failed to parse JSON data.");
  267. }
  268. }
  269. }
  270. public void SetBrightness(int value)
  271. {
  272. uvcManagerObj.Call("SetBrightness", value);
  273. }
  274. public void SetContrast(int value)
  275. {
  276. uvcManagerObj.Call("SetContrast", value);
  277. }
  278. public int SetCtrlValue(string type, Int32 value)
  279. {
  280. int result = -1;
  281. if (type == "PU_BRIGHTNESS")
  282. {
  283. uvcManagerObj.Call("SetBrightness", value);
  284. result = 0;
  285. }
  286. else if (type == "PU_CONTRAST")
  287. {
  288. uvcManagerObj.Call("SetContrast", value);
  289. result = 0;
  290. }
  291. return result;
  292. }
  293. //--------------------------------------------------------------------------------
  294. /**
  295. * 先处理相机权限
  296. */
  297. private void OpenCameraPermisson()
  298. {
  299. if (Permission.HasUserAuthorizedPermission(Permission.Camera))
  300. {
  301. //Debug.LogError("HasUserAuthorizedPermission!");
  302. systemCameraPermissionHandle?.Invoke();
  303. return;
  304. }
  305. bool useCallbacks = true;
  306. if (!useCallbacks)
  307. {
  308. // We do not have permission to use the microphone.
  309. // Ask for permission or proceed without the functionality enabled.
  310. Permission.RequestUserPermission(Permission.Camera);
  311. }
  312. else
  313. {
  314. var callbacks = new PermissionCallbacks();
  315. callbacks.PermissionDenied += PermissionCallbacks_PermissionDenied;
  316. callbacks.PermissionGranted += PermissionCallbacks_PermissionGranted;
  317. callbacks.PermissionDeniedAndDontAskAgain += PermissionCallbacks_PermissionDeniedAndDontAskAgain;
  318. Permission.RequestUserPermission(Permission.Camera, callbacks);
  319. }
  320. }
  321. void PermissionCallbacks_PermissionDenied(string PermissionName)
  322. {
  323. Debug.LogError($"PermissionCallbacks_PermissionDenied[{PermissionName}]");
  324. }
  325. //本次允许
  326. void PermissionCallbacks_PermissionGranted(string PermissionName)
  327. {
  328. Debug.Log($"PermissionCallbacks_PermissionGranted[{PermissionName}]");
  329. systemCameraPermissionHandle?.Invoke();
  330. }
  331. void PermissionCallbacks_PermissionDeniedAndDontAskAgain(string PermissionName)
  332. {
  333. Debug.Log($"PermissionCallbacks_PermissionDeniedAndDontAskAgain[{PermissionName}]");
  334. systemCameraPermissionHandle?.Invoke();
  335. }
  336. //设置GL纹理
  337. [DllImport("TransferTexture")]
  338. private static extern void SetTexture(IntPtr texture, int w, int h);
  339. //GL渲染事件
  340. [DllImport("TransferTexture")]
  341. private static extern IntPtr GetRenderEventFunc();
  342. [UnmanagedFunctionPointer(CallingConvention.StdCall)]
  343. public delegate void TextureUpdateDelegate(Int32 id, int width, int height, bool bUpdate);
  344. [DllImport("TransferTexture")]
  345. private static extern void RegisterTextureUpdateCallback(Int32 id, TextureUpdateDelegate callback);
  346. [DllImport("TransferTexture")]
  347. private static extern void UnregisterTextureUpdateCallback(Int32 id, TextureUpdateDelegate callback);
  348. //记录MyUVCInterface
  349. private static Dictionary<Int32, UVCInterface> mUVCInterfaces = new Dictionary<Int32, UVCInterface>();
  350. private static TextureUpdateDelegate textureUpdateDelegate;
  351. //注册回调事件
  352. public static void Add(UVCInterface myUVCInterface)
  353. {
  354. Int32 id = myUVCInterface.GetHashCode();
  355. textureUpdateDelegate = new TextureUpdateDelegate(TextureUpdateHandler);
  356. mUVCInterfaces.Add(id, myUVCInterface);
  357. RegisterTextureUpdateCallback(id, textureUpdateDelegate);
  358. }
  359. //移除回调事件
  360. public static void Remove(UVCInterface myUVCInterface)
  361. {
  362. Int32 id = myUVCInterface.GetHashCode();
  363. UnregisterTextureUpdateCallback(id, textureUpdateDelegate);
  364. mUVCInterfaces.Remove(id);
  365. }
  366. //数据更新时候回调
  367. [MonoPInvokeCallback(typeof(TextureUpdateDelegate))]
  368. private static void TextureUpdateHandler(Int32 id, int width, int height, bool bUpdate)
  369. {
  370. var myUVCInterface = mUVCInterfaces.ContainsKey(id) ? mUVCInterfaces[id] : null;
  371. if (myUVCInterface != null)
  372. {
  373. myUVCInterface.OnTextureUpdate(width, height, bUpdate);
  374. }
  375. }
  376. }
  377. }