using System; using System.Collections.Generic; using UnityEngine.XR.ARSubsystems; #if UNITY_XR_ARKIT_LOADER_ENABLED using System.Runtime.InteropServices; #endif 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(); /// /// 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. /// if the image plane was acquired. Otherwise, . public override bool TryGetPlane( int nativeHandle, int planeIndex, out XRCpuImage.Plane.Cinfo planeCinfo) => 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. /// /// A unique identifier for the camera image in question. /// , if it is a valid handle. Otherwise, . /// /// If a handle is valid, and should not fail. /// /// public override bool NativeHandleValid(int nativeHandle) => Native.HandleValid(nativeHandle); /// /// Tries to acquire the latest image of type . /// /// The type of image to acquire. /// On success, populated with construction information for an . /// if the latest image of type was successfully acquired. /// 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. /// if the output was set. Otherwise, . public override bool TryGetConvertedDataSize( int nativeHandle, Vector2Int dimensions, TextureFormat format, out int size) => 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. /// if the image was converted and stored in . /// Otherwise, . public override bool TryConvert( int nativeHandle, XRCpuImage.ConversionParams conversionParams, IntPtr destinationBuffer, int bufferLength) => 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 . /// 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. /// /// 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 successful or not. /// A native pointer which must be passed back unaltered to /// . /// /// 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 . /// 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() { 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. /// if can be converted to . /// Otherwise, . public override bool FormatSupported(XRCpuImage image, TextureFormat format) { return image.format switch { XRCpuImage.Format.IosYpCbCr420_8BiPlanarFullRange => s_SupportedVideoConversionFormats.Contains(format), XRCpuImage.Format.OneComponent8 => format is TextureFormat.R8 or TextureFormat.Alpha8, XRCpuImage.Format.DepthFloat32 => format == TextureFormat.RFloat, _ => false }; } 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 public static bool TryAcquireLatestImage(ImageType imageType, out XRCpuImage.Cinfo cinfo) => throw new NotImplementedException(Constants.k_LoaderDisabledExceptionMsg); public static void DisposeImage(int nativeHandle) => throw new NotImplementedException(Constants.k_LoaderDisabledExceptionMsg); public static bool TryGetPlane( int nativeHandle, int planeIndex, out XRCpuImage.Plane.Cinfo planeCinfo) => throw new NotImplementedException(Constants.k_LoaderDisabledExceptionMsg); public static bool HandleValid(int nativeHandle) => throw new NotImplementedException(Constants.k_LoaderDisabledExceptionMsg); public static XRCpuImage.AsyncConversionStatus GetAsyncRequestStatus(int requestId) => throw new NotImplementedException(Constants.k_LoaderDisabledExceptionMsg); public static void DisposeAsyncRequest(int requestHandle) => throw new NotImplementedException(Constants.k_LoaderDisabledExceptionMsg); public static bool TryGetConvertedDataSize( int nativeHandle, Vector2Int dimensions, TextureFormat format, out int size) => throw new NotImplementedException(Constants.k_LoaderDisabledExceptionMsg); public static bool TryConvert( int nativeHandle, XRCpuImage.ConversionParams conversionParams, IntPtr buffer, int bufferLength) => throw new NotImplementedException(Constants.k_LoaderDisabledExceptionMsg); public static int CreateAsyncConversionRequest( int nativeHandle, XRCpuImage.ConversionParams conversionParams) => throw new NotImplementedException(Constants.k_LoaderDisabledExceptionMsg); public static bool TryGetAsyncRequestData(int requestHandle, out IntPtr dataPtr, out int dataLength) => throw new NotImplementedException(Constants.k_LoaderDisabledExceptionMsg); public static void CreateAsyncConversionRequestWithCallback( int nativeHandle, XRCpuImage.ConversionParams conversionParams, OnImageRequestCompleteDelegate callback, IntPtr context) => throw new NotImplementedException(Constants.k_LoaderDisabledExceptionMsg); #endif } } }