NativeCameraProxy.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /****************************************************************************
  2. * Copyright 2019 Nreal Techonology Limited. All rights reserved.
  3. *
  4. * This file is part of NRSDK.
  5. *
  6. * https://www.nreal.ai/
  7. *
  8. *****************************************************************************/
  9. namespace NRKernal
  10. {
  11. using System;
  12. using UnityEngine;
  13. using System.Collections.Generic;
  14. using System.Threading.Tasks;
  15. /// <summary> A native camera proxy. </summary>
  16. public class NativeCameraProxy
  17. {
  18. /// <summary> The identifier. </summary>
  19. public static string ID = "NativeCameraProxy";
  20. /// <summary> Gets or sets the camera data provider. </summary>
  21. /// <value> The camera data provider. </value>
  22. protected ICameraDataProvider CameraDataProvider { get; private set; }
  23. /// <summary> The texture pointer. </summary>
  24. protected IntPtr m_TexturePtr = IntPtr.Zero;
  25. /// <summary> The current frame. </summary>
  26. protected FrameRawData m_CurrentFrame;
  27. /// <summary> Gets the resolution. </summary>
  28. /// <value> The resolution. </value>
  29. public virtual NativeResolution Resolution { get; }
  30. /// <summary> True if is initialized, false if not. </summary>
  31. private bool m_IsInitialized = false;
  32. /// <summary> True if the format has been set, false if not. </summary>
  33. private bool m_IsImageFormatSet = false;
  34. /// <summary> The last frame. </summary>
  35. protected int m_LastFrame = -1;
  36. /// <summary> True if is playing, false if not. </summary>
  37. protected bool m_IsPlaying = false;
  38. /// <summary> Gets a value indicating whether this object is camera playing. </summary>
  39. /// <value> True if this object is camera playing, false if not. </value>
  40. public bool IsCamPlaying
  41. {
  42. get
  43. {
  44. return m_IsPlaying;
  45. }
  46. }
  47. /// <summary> Interface of external frame consumer. </summary>
  48. public interface IExternFrameConsumer
  49. {
  50. void UpdateFrame(FrameRawData frame);
  51. }
  52. protected IExternFrameConsumer m_ExternFrameConsumer;
  53. public void RegisterFrameConsumer(IExternFrameConsumer consumer)
  54. {
  55. m_ExternFrameConsumer = consumer;
  56. }
  57. /// <summary> Queue of fixed sized. </summary>
  58. public class FixedSizedQueue
  59. {
  60. /// <summary> The queue. </summary>
  61. private Queue<FrameRawData> m_Queue = new Queue<FrameRawData>();
  62. /// <summary> The lock object. </summary>
  63. private object m_LockObj = new object();
  64. /// <summary> The object pool. </summary>
  65. private ObjectPool m_ObjectPool;
  66. /// <summary> Constructor. </summary>
  67. /// <param name="pool"> The pool.</param>
  68. public FixedSizedQueue(ObjectPool pool)
  69. {
  70. m_ObjectPool = pool;
  71. }
  72. /// <summary> Gets or sets the limit. </summary>
  73. /// <value> The limit. </value>
  74. public int Limit { get; set; }
  75. /// <summary> Gets the number of. </summary>
  76. /// <value> The count. </value>
  77. public int Count
  78. {
  79. get
  80. {
  81. lock (m_LockObj)
  82. {
  83. return m_Queue.Count;
  84. }
  85. }
  86. }
  87. /// <summary> Adds an object onto the end of this queue. </summary>
  88. /// <param name="obj"> The object.</param>
  89. public void Enqueue(FrameRawData obj)
  90. {
  91. lock (m_LockObj)
  92. {
  93. m_Queue.Enqueue(obj);
  94. if (m_Queue.Count > Limit)
  95. {
  96. var frame = m_Queue.Dequeue();
  97. m_ObjectPool.Put<FrameRawData>(frame);
  98. }
  99. }
  100. }
  101. /// <summary> Removes the head object from this queue. </summary>
  102. /// <returns> The head object from this queue. </returns>
  103. public FrameRawData Dequeue()
  104. {
  105. lock (m_LockObj)
  106. {
  107. var frame = m_Queue.Dequeue();
  108. m_ObjectPool.Put<FrameRawData>(frame);
  109. return frame;
  110. }
  111. }
  112. public void Clear()
  113. {
  114. m_ObjectPool.Clear();
  115. m_Queue.Clear();
  116. }
  117. }
  118. /// <summary> The camera frames. </summary>
  119. protected FixedSizedQueue m_CameraFrames;
  120. /// <summary> The frame pool. </summary>
  121. protected ObjectPool FramePool;
  122. /// <summary> The active textures. </summary>
  123. protected List<CameraModelView> m_ActiveTextures;
  124. public List<CameraModelView> ActiveTextures
  125. {
  126. get
  127. {
  128. return m_ActiveTextures;
  129. }
  130. }
  131. /// <summary> Specialized constructor for use only by derived class. </summary>
  132. /// <param name="provider"> The provider.</param>
  133. protected NativeCameraProxy(ICameraDataProvider provider)
  134. {
  135. CameraDataProvider = provider;
  136. this.Initialize();
  137. }
  138. /// <summary> Initializes this object. </summary>
  139. public virtual void Initialize()
  140. {
  141. if (m_IsInitialized)
  142. {
  143. return;
  144. }
  145. NRDebugger.Info("[NativeCameraProxy] Initialize");
  146. if (FramePool == null)
  147. {
  148. FramePool = new ObjectPool();
  149. FramePool.InitCount = 10;
  150. }
  151. if (m_CameraFrames == null)
  152. {
  153. m_CameraFrames = new FixedSizedQueue(FramePool);
  154. m_CameraFrames.Limit = 5;
  155. }
  156. m_ActiveTextures = new List<CameraModelView>();
  157. CameraDataProvider.Create();
  158. m_IsInitialized = true;
  159. }
  160. /// <summary> Callback, called when the regist capture. </summary>
  161. /// <param name="callback"> The callback.</param>
  162. protected void RegistCaptureCallback(CameraImageCallback callback)
  163. {
  164. CameraDataProvider.SetCaptureCallback(callback);
  165. }
  166. /// <summary> Regists the given tex. </summary>
  167. /// <param name="tex"> The tex to remove.</param>
  168. public void Regist(CameraModelView tex)
  169. {
  170. if (m_ActiveTextures == null)
  171. {
  172. m_ActiveTextures = new List<CameraModelView>();
  173. }
  174. if (!m_ActiveTextures.Contains(tex))
  175. {
  176. m_ActiveTextures.Add(tex);
  177. }
  178. NRDebugger.Debug("[NativeCamera] Regist:" + m_ActiveTextures.Count);
  179. }
  180. public static CameraImageFormat GetActiveCameraImageFormat(string id)
  181. {
  182. NativeCameraProxy controller = CameraProxyFactory.GetInstance(id);
  183. if (controller != null && controller.ActiveTextures != null && controller.ActiveTextures.Count > 0)
  184. {
  185. NRDebugger.Info("[NativeCamera] Use the first texture format:" + controller.ActiveTextures[0].ImageFormat.ToString());
  186. return controller.ActiveTextures[0].ImageFormat;
  187. }
  188. else
  189. {
  190. NRDebugger.Info("[NativeCamera] Use the default texture format: RGB_888");
  191. return CameraImageFormat.RGB_888;
  192. }
  193. }
  194. /// <summary> Removes the given tex. </summary>
  195. /// <param name="tex"> The tex to remove.</param>
  196. public void Remove(CameraModelView tex)
  197. {
  198. if (m_ActiveTextures != null && m_ActiveTextures.Contains(tex))
  199. {
  200. m_ActiveTextures.Remove(tex);
  201. }
  202. NRDebugger.Debug("[NativeCamera] Remove:" + m_ActiveTextures.Count);
  203. }
  204. /// <summary> Sets image format. </summary>
  205. /// <param name="format"> Describes the format to use.</param>
  206. public void SetImageFormat(CameraImageFormat format)
  207. {
  208. if (!m_IsInitialized)
  209. {
  210. Initialize();
  211. }
  212. if (m_IsImageFormatSet)
  213. {
  214. return;
  215. }
  216. m_IsImageFormatSet = CameraDataProvider.SetImageFormat(format);
  217. NRDebugger.Info("[NativeCameraProxy] SetImageFormat : " + format.ToString());
  218. }
  219. /// <summary> Start to play camera. </summary>
  220. public void Play()
  221. {
  222. if (!m_IsInitialized)
  223. {
  224. Initialize();
  225. }
  226. if (m_IsPlaying)
  227. {
  228. return;
  229. }
  230. m_IsPlaying = true;
  231. NRDebugger.Info("[NativeCameraProxy] StartCapture begin.");
  232. //System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
  233. //stopwatch.Start();
  234. CameraDataProvider.StartCapture();
  235. NRDebugger.Info("[NativeCameraProxy] StartCapture end.");
  236. //NRDebugger.Info("[NativeCameraProxy] Start to play, result:{0} cost:{1}ms", m_IsPlaying, stopwatch.ElapsedMilliseconds);
  237. }
  238. /// <summary> Query if this object has frame. </summary>
  239. /// <returns> True if frame, false if not. </returns>
  240. public bool HasFrame()
  241. {
  242. // To prevent the problem that the object behind can not be acquired when the same frame is fetched more than once.
  243. if (Time.frameCount == m_LastFrame)
  244. {
  245. return true;
  246. }
  247. return m_IsPlaying && m_CameraFrames.Count > 0;
  248. }
  249. /// <summary> Gets the frame. </summary>
  250. /// <returns> The frame. </returns>
  251. public FrameRawData GetFrame()
  252. {
  253. if (Time.frameCount != m_LastFrame && m_CameraFrames.Count > 0)
  254. {
  255. // Get the newest frame of the queue.
  256. m_CurrentFrame = m_CameraFrames.Dequeue();
  257. m_LastFrame = Time.frameCount;
  258. }
  259. return m_CurrentFrame;
  260. }
  261. /// <summary> Updates the frame. </summary>
  262. /// <param name="camera_handle"> Handle of the camera.</param>
  263. /// <param name="camera_image_handle"> Handle of the camera image.</param>
  264. /// <param name="userdata"> The userdata.</param>
  265. public virtual void UpdateFrame(UInt64 camera_handle, UInt64 camera_image_handle, UInt64 userdata) { }
  266. /// <summary> Queue frame. </summary>
  267. /// <param name="textureptr"> The textureptr.</param>
  268. /// <param name="size"> The size.</param>
  269. /// <param name="timestamp"> The timestamp.</param>
  270. protected void QueueFrame(IntPtr textureptr, int size, UInt64 timestamp)
  271. {
  272. if (!m_IsPlaying)
  273. {
  274. NRDebugger.Error("camera was not stopped properly, it still sending data.");
  275. return;
  276. }
  277. FrameRawData frame = FramePool.Get<FrameRawData>();
  278. bool result = FrameRawData.MakeSafe(m_TexturePtr, size, timestamp, ref frame);
  279. if (result)
  280. {
  281. m_CameraFrames.Enqueue(frame);
  282. if (m_ExternFrameConsumer != null)
  283. {
  284. m_ExternFrameConsumer.UpdateFrame(frame);
  285. }
  286. }
  287. else
  288. {
  289. FramePool.Put<FrameRawData>(frame);
  290. }
  291. }
  292. /// <summary> Stop the camera. </summary>
  293. public virtual void Stop()
  294. {
  295. if (!m_IsPlaying)
  296. {
  297. return;
  298. }
  299. // If there is no a active texture, pause and release camera resource.
  300. if (m_ActiveTextures.Count == 0)
  301. {
  302. m_IsPlaying = false;
  303. NRDebugger.Info("[NativeCameraProxy] StopCapture begin.");
  304. //System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
  305. //stopwatch.Start();
  306. CameraDataProvider.StopCapture();
  307. NRDebugger.Info("[NativeCameraProxy] StopCapture end.");
  308. //NRDebugger.Info("[NativeCameraProxy] Stop rgbcamera, result:{0} cost:{1}ms", m_IsPlaying, stopwatch.ElapsedMilliseconds);
  309. Release();
  310. }
  311. }
  312. /// <summary> Release the camera. </summary>
  313. protected virtual void Release()
  314. {
  315. if (CameraDataProvider == null)
  316. {
  317. return;
  318. }
  319. NRDebugger.Info("[NativeCameraProxy] Release");
  320. CameraDataProvider.Release();
  321. m_CameraFrames.Clear();
  322. m_CameraFrames = null;
  323. m_CurrentFrame.data = null;
  324. m_ActiveTextures.Clear();
  325. m_ActiveTextures = null;
  326. m_IsInitialized = false;
  327. m_IsImageFormatSet = false;
  328. m_IsPlaying = false;
  329. }
  330. }
  331. }