/****************************************************************************
* 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);
}
}