using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine.XR.ARSubsystems;
namespace UnityEngine.XR.ARKit
{
class ARKitCpuImageApi : XRCpuImage.Api
{
///
/// The type of image to acquire. Used by .
///
public enum ImageType
{
Camera,
HumanDepth,
HumanStencil,
EnvironmentDepth,
EnvironmentDepthConfidence,
RawEnvironmentDepth,
TemporallySmoothedEnvironmentDepth,
}
///
/// The shared API instance.
///
public static ARKitCpuImageApi instance { get; } = new ARKitCpuImageApi();
///
/// Dispose an existing native image identified by .
///
/// A unique identifier for this camera image.
public override void DisposeImage(int nativeHandle) => Native.DisposeImage(nativeHandle);
///
/// Get information about an image plane from a native image handle by index.
///
/// A unique identifier for this camera image.
/// The index of the plane to get.
/// The returned camera plane information if successful.
///
/// true if the image plane was acquired. Otherwise, false.
///
public override bool TryGetPlane(
int nativeHandle,
int planeIndex,
out XRCpuImage.Plane.Cinfo planeCinfo)
{
return Native.TryGetPlane(nativeHandle, planeIndex, out planeCinfo);
}
///
/// Determine whether a native image handle returned by
/// is currently valid. An image can
/// become invalid if it has been disposed.
///
///
/// If a handle is valid, and should not fail.
///
/// A unique identifier for the camera image in question.
/// true, if it is a valid handle. Otherwise, false.
///
public override bool NativeHandleValid(int nativeHandle) => Native.HandleValid(nativeHandle);
///
/// Tries to acquire the latest image of a particular type.
///
/// The type of image to acquire.
/// On success, populated with construction information information for a
/// .
/// Returns `true` if the latest image of type was successfully acquired.
/// Returns `false` otherwise.
public static bool TryAcquireLatestImage(ImageType imageType, out XRCpuImage.Cinfo cinfo)
=> Native.TryAcquireLatestImage(imageType, out cinfo);
///
/// Get the status of an existing asynchronous conversion request.
///
/// The unique identifier associated with a request.
/// The state of the request.
///
public override XRCpuImage.AsyncConversionStatus GetAsyncRequestStatus(int requestId)
=> Native.GetAsyncRequestStatus(requestId);
///
/// Dispose an existing async conversion request.
///
/// A unique identifier for the request.
///
public override void DisposeAsyncRequest(int requestId) => Native.DisposeAsyncRequest(requestId);
///
/// Get the number of bytes required to store an image with the given dimensions and
/// [TextureFormat](https://docs.unity3d.com/ScriptReference/TextureFormat.html).
///
/// A unique identifier for the camera image to convert.
/// The dimensions of the output image.
/// The TextureFormat for the image.
/// The number of bytes required to store the converted image.
/// true if the output was set.
public override bool TryGetConvertedDataSize(
int nativeHandle,
Vector2Int dimensions,
TextureFormat format,
out int size)
{
return Native.TryGetConvertedDataSize(nativeHandle, dimensions, format, out size);
}
///
/// Convert the image with handle using the provided
/// .
///
/// A unique identifier for the camera image to convert.
/// The parameters to use during the conversion.
/// A buffer to write the converted image to.
/// The number of bytes available in the buffer.
///
/// true if the image was converted and stored in .
///
public override bool TryConvert(
int nativeHandle,
XRCpuImage.ConversionParams conversionParams,
IntPtr destinationBuffer,
int bufferLength)
{
return Native.TryConvert(nativeHandle, conversionParams, destinationBuffer, bufferLength);
}
///
/// Create an asynchronous request to convert a camera image, similar to except
/// the conversion should happen on a thread other than the calling (main) thread.
///
/// A unique identifier for the camera image to convert.
/// The parameters to use during the conversion.
/// A unique identifier for this request.
public override int ConvertAsync(int nativeHandle, XRCpuImage.ConversionParams conversionParams)
=> Native.CreateAsyncConversionRequest(nativeHandle, conversionParams);
///
/// Get a pointer to the image data from a completed asynchronous request. This method should only succeed
/// if returns .
///
/// The unique identifier associated with a request.
/// A pointer to the native buffer containing the data.
/// The number of bytes in .
/// true if and were set and point
/// to the image data.
public override bool TryGetAsyncRequestData(int requestId, out IntPtr dataPtr, out int dataLength)
=> Native.TryGetAsyncRequestData(requestId, out dataPtr, out dataLength);
///
/// Similar to but takes a delegate to
/// invoke when the request is complete, rather than returning a request id.
///
///
/// If the first parameter to is
/// then the dataPtr parameter must be valid
/// for the duration of the invocation. The data can be destroyed immediately upon return. The
/// parameter must be passed back to the .
///
/// A unique identifier for the camera image to convert.
/// The parameters to use during the conversion.
/// A delegate which must be invoked when the request is complete, whether the
/// conversion was successfully or not.
/// A native pointer which must be passed back unaltered to
/// .
public override void ConvertAsync(
int nativeHandle,
XRCpuImage.ConversionParams conversionParams,
OnImageRequestCompleteDelegate callback,
IntPtr context)
{
Native.CreateAsyncConversionRequestWithCallback(
nativeHandle, conversionParams, callback, context);
}
static readonly HashSet s_SupportedVideoConversionFormats = new HashSet
{
TextureFormat.Alpha8,
TextureFormat.R8,
TextureFormat.RGB24,
TextureFormat.RGBA32,
TextureFormat.ARGB32,
TextureFormat.BGRA32,
};
///
/// Determines whether a given
/// [TextureFormat](https://docs.unity3d.com/ScriptReference/TextureFormat.html) is supported for image
/// conversion.
///
/// The to convert.
/// The [TextureFormat](https://docs.unity3d.com/ScriptReference/TextureFormat.html)
/// to test.
/// Returns `true` if can be converted to .
/// Returns `false` otherwise.
public override bool FormatSupported(XRCpuImage image, TextureFormat format)
{
switch (image.format)
{
case XRCpuImage.Format.IosYpCbCr420_8BiPlanarFullRange:
return s_SupportedVideoConversionFormats.Contains(format);
case XRCpuImage.Format.OneComponent8:
return
format == TextureFormat.R8 ||
format == TextureFormat.Alpha8;
case XRCpuImage.Format.DepthFloat32:
return format == TextureFormat.RFloat;
default:
return false;
}
}
public static class Native
{
#if UNITY_XR_ARKIT_LOADER_ENABLED
[DllImport("__Internal", EntryPoint = "UnityARKit_CpuImage_TryAcquireLatestImage")]
public static extern bool TryAcquireLatestImage(ImageType imageType, out XRCpuImage.Cinfo cinfo);
[DllImport("__Internal", EntryPoint = "UnityARKit_CpuImage_DisposeImage")]
public static extern void DisposeImage(int nativeHandle);
[DllImport("__Internal", EntryPoint = "UnityARKit_CpuImage_TryGetPlane")]
public static extern bool TryGetPlane(
int nativeHandle, int planeIndex,
out XRCpuImage.Plane.Cinfo planeCinfo);
[DllImport("__Internal", EntryPoint = "UnityARKit_CpuImage_HandleValid")]
public static extern bool HandleValid(int nativeHandle);
[DllImport("__Internal", EntryPoint = "UnityARKit_CpuImage_GetAsyncRequestStatus")]
public static extern XRCpuImage.AsyncConversionStatus GetAsyncRequestStatus(int requestId);
[DllImport("__Internal", EntryPoint = "UnityARKit_CpuImage_DisposeAsyncRequest")]
public static extern void DisposeAsyncRequest(int requestHandle);
[DllImport("__Internal", EntryPoint = "UnityARKit_CpuImage_TryGetConvertedDataSize")]
public static extern bool TryGetConvertedDataSize(
int nativeHandle, Vector2Int dimensions, TextureFormat format, out int size);
[DllImport("__Internal", EntryPoint = "UnityARKit_CpuImage_TryConvert")]
public static extern bool TryConvert(
int nativeHandle, XRCpuImage.ConversionParams conversionParams,
IntPtr buffer, int bufferLength);
[DllImport("__Internal", EntryPoint = "UnityARKit_CpuImage_CreateAsyncConversionRequest")]
public static extern int CreateAsyncConversionRequest(
int nativeHandle, XRCpuImage.ConversionParams conversionParams);
[DllImport("__Internal", EntryPoint = "UnityARKit_CpuImage_TryGetAsyncRequestData")]
public static extern bool TryGetAsyncRequestData(
int requestHandle, out IntPtr dataPtr, out int dataLength);
[DllImport("__Internal", EntryPoint = "UnityARKit_CpuImage_CreateAsyncConversionRequestWithCallback")]
public static extern void CreateAsyncConversionRequestWithCallback(
int nativeHandle, XRCpuImage.ConversionParams conversionParams,
OnImageRequestCompleteDelegate callback, IntPtr context);
#else
static readonly string k_ExceptionMsg = "ARKit Plugin Provider not enabled in project settings.";
public static bool TryAcquireLatestImage(ImageType imageType, out XRCpuImage.Cinfo cinfo)
{
throw new System.NotImplementedException(k_ExceptionMsg);
}
public static void DisposeImage(int nativeHandle)
{
throw new System.NotImplementedException(k_ExceptionMsg);
}
public static bool TryGetPlane(
int nativeHandle, int planeIndex,
out XRCpuImage.Plane.Cinfo planeCinfo)
{
throw new System.NotImplementedException(k_ExceptionMsg);
}
public static bool HandleValid(int nativeHandle)
{
throw new System.NotImplementedException(k_ExceptionMsg);
}
public static XRCpuImage.AsyncConversionStatus GetAsyncRequestStatus(int requestId)
{
throw new System.NotImplementedException(k_ExceptionMsg);
}
public static void DisposeAsyncRequest(int requestHandle)
{
throw new System.NotImplementedException(k_ExceptionMsg);
}
public static bool TryGetConvertedDataSize(
int nativeHandle, Vector2Int dimensions, TextureFormat format, out int size)
{
throw new System.NotImplementedException(k_ExceptionMsg);
}
public static bool TryConvert(
int nativeHandle, XRCpuImage.ConversionParams conversionParams,
IntPtr buffer, int bufferLength)
{
throw new System.NotImplementedException(k_ExceptionMsg);
}
public static int CreateAsyncConversionRequest(
int nativeHandle, XRCpuImage.ConversionParams conversionParams)
{
throw new System.NotImplementedException(k_ExceptionMsg);
}
public static bool TryGetAsyncRequestData(
int requestHandle, out IntPtr dataPtr, out int dataLength)
{
throw new System.NotImplementedException(k_ExceptionMsg);
}
public static void CreateAsyncConversionRequestWithCallback(
int nativeHandle, XRCpuImage.ConversionParams conversionParams,
OnImageRequestCompleteDelegate callback, IntPtr context)
{
throw new System.NotImplementedException(k_ExceptionMsg);
}
#endif
}
}
}