/**************************************************************************** * Copyright 2019 Nreal Techonology Limited. All rights reserved. * * This file is part of NRSDK. * * https://www.nreal.ai/ * *****************************************************************************/ namespace NRKernal.Record { using System; using UnityEngine; using System.Collections.Generic; /// A nr photo capture. public class NRPhotoCapture : IDisposable { private const int CameraDataReadyTimeOut = 3000; /// The supported resolutions. private static IEnumerable m_SupportedResolutions; /// A list of all the supported device resolutions for taking pictures. /// The supported resolutions. public static IEnumerable SupportedResolutions { get { if (m_SupportedResolutions == null) { var resolutions = new List(); var resolution = new Resolution(); NativeResolution rgbResolution = new NativeResolution(1280, 720); if (NRDevice.Subsystem.IsFeatureSupported(NRSupportedFeature.NR_FEATURE_RGB_CAMERA)) rgbResolution = NRFrame.GetDeviceResolution(NativeDevice.RGB_CAMERA); resolution.width = rgbResolution.width; resolution.height = rgbResolution.height; resolutions.Add(resolution); m_SupportedResolutions = resolutions; } return m_SupportedResolutions; } } /// Context for the capture. private FrameCaptureContext m_CaptureContext; /// Gets the preview texture. /// The preview texture. public Texture PreviewTexture { get { return m_CaptureContext?.PreviewTexture; } } /// Creates an asynchronous. /// True to show, false to hide the holograms. /// The on created callback. public static void CreateAsync(bool showHolograms, OnCaptureResourceCreatedCallback onCreatedCallback) { NRPhotoCapture photocapture = new NRPhotoCapture(); photocapture.m_CaptureContext = FrameCaptureContextFactory.Create(); onCreatedCallback?.Invoke(photocapture); } /// Dispose must be called to shutdown the PhotoCapture instance. public void Dispose() { if (m_CaptureContext != null) { m_CaptureContext.Release(); m_CaptureContext = null; } } /// /// Provides a COM pointer to the native IVideoDeviceController. A native COM pointer to the /// IVideoDeviceController. /// The unsafe pointer to video device controller. public IntPtr GetUnsafePointerToVideoDeviceController() { NRDebugger.Warning("[NRPhotoCapture] Interface not supported..."); return IntPtr.Zero; } /// Starts photo mode asynchronous. /// Options for controlling the setup. /// The on photo mode started callback. /// Auto adaption for BlendMode based on supported feature on current device. public void StartPhotoModeAsync(CameraParameters setupParams, OnPhotoModeStartedCallback onPhotoModeStartedCallback, bool autoAdaptBlendMode = false) { PhotoCaptureResult result = new PhotoCaptureResult(); try { setupParams.camMode = CamMode.PhotoMode; if (autoAdaptBlendMode) { var blendMode = m_CaptureContext.AutoAdaptBlendMode(setupParams.blendMode); if (blendMode != setupParams.blendMode) { NRDebugger.Warning("[PhotoCapture] AutoAdaptBlendMode : {0} => {1}", setupParams.blendMode, blendMode); setupParams.blendMode = blendMode; } } if (setupParams.frameRate <= 0) NRDebugger.Warning("[PhotoCapture] frameRate need to be bigger than zero"); m_CaptureContext.StartCaptureMode(setupParams); m_CaptureContext.StartCapture(); NRKernalUpdater.Instance.StartCoroutine(OnPhotoModeStartedReady((ready) => { if (ready) { result.resultType = CaptureResultType.Success; } else { result.resultType = CaptureResultType.TimeOutError; } onPhotoModeStartedCallback?.Invoke(result); })); } catch (Exception) { result.resultType = CaptureResultType.UnknownError; onPhotoModeStartedCallback?.Invoke(result); throw; } } /// Executes the 'photo mode started ready' action. /// The callback. /// A list of. private System.Collections.IEnumerator OnPhotoModeStartedReady(Action callback) { System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch(); stopwatch.Start(); while (!this.m_CaptureContext.GetFrameProvider().IsFrameReady()) { if (stopwatch.ElapsedMilliseconds > CameraDataReadyTimeOut) { callback?.Invoke(false); NRDebugger.Error("[PhotoCapture] Get rgbcamera data timeout..."); yield break; } NRDebugger.Debug("[PhotoCapture] Wait for the first frame ready..."); yield return new WaitForEndOfFrame(); } yield return new WaitForEndOfFrame(); yield return new WaitForEndOfFrame(); yield return new WaitForEndOfFrame(); callback?.Invoke(true); } /// Stops photo mode asynchronous. /// The on photo mode stopped callback. public void StopPhotoModeAsync(OnPhotoModeStoppedCallback onPhotoModeStoppedCallback) { PhotoCaptureResult result = new PhotoCaptureResult(); try { m_CaptureContext.StopCaptureMode(); result.resultType = CaptureResultType.Success; onPhotoModeStoppedCallback?.Invoke(result); } catch (Exception) { result.resultType = CaptureResultType.UnknownError; onPhotoModeStoppedCallback?.Invoke(result); throw; } } /// Take photo asynchronous. /// Filename of the file. /// The file output format. /// The on captured photo disk callback. public void TakePhotoAsync(string filename, PhotoCaptureFileOutputFormat fileOutputFormat, OnCapturedToDiskCallback onCapturedPhotoToDiskCallback) { try { var capture = m_CaptureContext.GetBehaviour(); ((NRCaptureBehaviour)capture).Do(filename, fileOutputFormat); } catch (Exception) { throw; } } /// Take photo asynchronous. /// The on captured photo memory callback. public void TakePhotoAsync(OnCapturedToMemoryCallback onCapturedPhotoToMemoryCallback) { try { var capture = m_CaptureContext.GetBehaviour(); ((NRCaptureBehaviour)capture).DoAsyn(onCapturedPhotoToMemoryCallback); } catch (Exception) { throw; } } /// Contains the result of the capture request. public enum CaptureResultType { /// /// Specifies that the desired operation was successful. /// Success = 0, /// /// Specifies that an unknown error occurred. /// UnknownError = 1, /// /// Get rgb camera data timeout. /// TimeOutError = 2, } /// /// A data container that contains the result information of a photo capture operation. public struct PhotoCaptureResult { /// /// A generic result that indicates whether or not the PhotoCapture operation succeeded. public CaptureResultType resultType; /// The specific HResult value. public long hResult; /// Indicates whether or not the operation was successful. /// True if success, false if not. public bool success { get { return resultType == CaptureResultType.Success; } } } /// Called when a PhotoCapture resource has been created. /// The PhotoCapture instance. public delegate void OnCaptureResourceCreatedCallback(NRPhotoCapture captureObject); /// Called when photo mode has been started. /// Indicates whether or not photo mode was successfully activated. public delegate void OnPhotoModeStartedCallback(PhotoCaptureResult result); /// Called when photo mode has been stopped. /// Indicates whether or not photo mode was successfully deactivated. public delegate void OnPhotoModeStoppedCallback(PhotoCaptureResult result); /// Called when a photo has been saved to the file system. /// Indicates whether or not the photo was successfully saved to the file /// system. public delegate void OnCapturedToDiskCallback(PhotoCaptureResult result); /// Called when a photo has been captured to memory. /// Indicates whether or not the photo was successfully captured /// to memory. /// Contains the target texture.If available, the spatial /// information will be accessible through this structure as well. public delegate void OnCapturedToMemoryCallback(PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame); } }