// %BANNER_BEGIN%
// ---------------------------------------------------------------------
// %COPYRIGHT_BEGIN%
// Copyright (c) (2018-2024) Magic Leap, Inc. All Rights Reserved.
// Use of this file is governed by the Software License Agreement, located here: https://www.magicleap.com/software-license-agreement-ml2
// Terms and conditions applicable to third-party materials accompanying this distribution may also be found in the top-level NOTICE file appearing herein.
// %COPYRIGHT_END%
// ---------------------------------------------------------------------
// %BANNER_END%
using System;
using System.Linq;
using System.Runtime.InteropServices;
namespace UnityEngine.XR.MagicLeap
{
public partial class MLCameraBase
{
internal partial class NativeBindings
{
///
/// Structure to encapsulate connection settings for MR capture.
///
[StructLayout(LayoutKind.Sequential)]
public struct MLCameraMRConnectInfo
{
///
/// MR video quality
///
public MLCamera.MRQuality MrQuality;
///
/// blending type for mixed reality capture
///
public MLCamera.MRBlendType MrBlendType;
///
/// capture frame rate
///
public MLCamera.CaptureFrameRate FrameRate;
///
/// Create and return an initialized version of this struct.
///
/// A new instance of this struct.
public static MLCameraMRConnectInfo Create(MLCamera.MRConnectInfo connectInfo)
{
return new MLCameraMRConnectInfo()
{
MrQuality = connectInfo.MRQuality,
MrBlendType = connectInfo.MRBlendType,
FrameRate = connectInfo.FrameRate
};
}
}
///
/// Structure to encapsulate context for a CameraConnect Request.
///
[StructLayout(LayoutKind.Sequential)]
public struct MLCameraConnectContext
{
///
/// version contains the version number for this structure.
///
public uint Version;
///
/// logical camera idenitifier
///
public MLCamera.Identifier CamId;
///
/// The Context in which the camera should operate in.
///
public MLCamera.ConnectFlag Flags;
///
/// Video Stabilization enable/disable 1 - enable 0 - disabled
///
[MarshalAs(UnmanagedType.I1)]
public bool EnableVideoStab;
///
/// MR capture connection settings
///
public MLCameraMRConnectInfo MrInfo;
///
/// Create and return an initialized version of this struct.
///
/// A new instance of this struct.
public static MLCameraConnectContext Create(MLCamera.ConnectContext cameraContext)
{
return new MLCameraConnectContext()
{
Version = 1,
CamId = cameraContext.CamId,
Flags = cameraContext.Flags,
EnableVideoStab = cameraContext.EnableVideoStabilization,
MrInfo = MLCameraMRConnectInfo.Create(cameraContext.MixedRealityConnectInfo)
};
}
}
///
/// The capabilities for each stream supported by logical camera device * can be queried with MLCameraGetDeviceCaps
///
[StructLayout(LayoutKind.Sequential)]
public struct MLCameraCaptureStreamCaps
{
///
/// capture_type Video, Image ,Preview
///
public MLCamera.CaptureType CaptureType;
///
/// Capture Resolution
///
public int Width;
///
/// Resolution height
///
public int Height;
///
/// Create and return an initialized version of this struct.
///
/// A new instance of this struct.
public static MLCameraCaptureStreamCaps Create()
{
return new MLCameraCaptureStreamCaps()
{
};
}
}
///
/// Structure to encapsulate stream configurations
///
[StructLayout(LayoutKind.Sequential)]
public struct MLCameraCaptureStreamConfig
{
///
/// capture_type Image Preview
///
public MLCamera.CaptureType CaptureType;
///
/// Capture Resolution
///
public int Width;
///
/// Resolution height
///
public int Height;
///
/// output Format
///
public MLCamera.OutputFormat OutputFormat;
///
/// media recorder surface, only valid for capture type video * set to ML_INVALID_HANDLE for yuv/rgba video capture
///
public ulong MediaRecorderSurfaceHandle;
///
/// Create and return an initialized version of this struct.
///
/// A new instance of this struct.
public static MLCameraCaptureStreamConfig Create()
{
return new MLCameraCaptureStreamConfig()
{
};
}
public static MLCameraCaptureStreamConfig Create(MLCamera.CaptureStreamConfig config)
{
return new MLCameraCaptureStreamConfig()
{
Height = config.Height,
Width = config.Width,
CaptureType = config.CaptureType,
OutputFormat = config.OutputFormat,
MediaRecorderSurfaceHandle = config.Surface?.Handle ?? InvalidHandle,
};
}
}
///
/// Structure to encapsulate capture configuration
///
[StructLayout(LayoutKind.Sequential)]
public struct MLCameraCaptureConfig
{
///
/// version contains the version number for this structure.
///
public uint Version;
///
/// capture frame rate
///
public MLCamera.CaptureFrameRate CaptureFrameRate;
///
/// no of capture streams.
///
public uint NumStreams;
///
/// Stream configurations
///
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MLCameraMaxStreams)]
public MLCameraCaptureStreamConfig[] StreamConfig;
///
/// Create and return an initialized version of this struct.
///
/// A new instance of this struct.
public static MLCameraCaptureConfig Create()
{
return new MLCameraCaptureConfig()
{
Version = 1,
StreamConfig = new MLCameraCaptureStreamConfig[MLCameraMaxStreams]
};
}
///
/// Create and initialize this native struct based on values exposed in .
///
/// A new instance of this struct.
public static MLCameraCaptureConfig Create(MLCamera.CaptureConfig config)
{
MLCameraCaptureConfig nativeConfig = MLCameraCaptureConfig.Create();
nativeConfig.NumStreams = (uint)config.StreamConfigs.Length;
nativeConfig.CaptureFrameRate = config.CaptureFrameRate;
for (var i = 0; i < config.StreamConfigs.Length; i++)
nativeConfig.StreamConfig[i] = MLCameraCaptureStreamConfig.Create(config.StreamConfigs[i]);
return nativeConfig;
}
}
///
/// Per plane info for captured output
///
[StructLayout(LayoutKind.Sequential)]
public struct MLCameraPlaneInfo
{
///
/// version contains the version number for this structure.
///
public uint Version;
///
/// Width of the output image in pixels
///
public uint Width;
///
/// Height of the output image in pixels
///
public uint Height;
///
/// Stride of the output image in pixels
///
public uint Stride;
///
/// Number of bytes used to represent a pixel
///
public uint BytesPerPixel;
public uint PixelsStride;
///
/// Image data
///
public IntPtr Data;
///
/// Number of bytes in the image output data
///
public uint Size;
///
/// Create and return an initialized version of this struct.
///
/// Returns a new MLCamera.PlaneInfo structure.
public static MLCameraPlaneInfo Create()
{
return new MLCameraPlaneInfo
{
Version = 0u,
Width = 0u,
Height = 0u,
Stride = 0u,
BytesPerPixel = 0u,
PixelsStride = 0u,
Data = IntPtr.Zero,
Size = 0u
};
}
public MLCamera.PlaneInfo CreatePlaneInfo(bool copyToManagedMemory, byte[] byteArrayToUse = null)
{
if (copyToManagedMemory && byteArrayToUse == null)
{
byteArrayToUse = new byte[Size];
}
var planeInfo = new MLCamera.PlaneInfo()
{
IsValid = true,
Width = this.Width,
Height = this.Height,
Stride = this.Stride,
BytesPerPixel = this.BytesPerPixel,
PixelStride = this.PixelsStride,
DataPtr = this.Data,
Size = this.Size,
Data = (copyToManagedMemory) ? byteArrayToUse : null
};
if (planeInfo.Data != null)
{
uint width = planeInfo.Stride == 0 ? planeInfo.Width : planeInfo.Stride;
planeInfo.Data = new byte[width * planeInfo.Height];
if (planeInfo.PixelStride == 2)
{
Marshal.Copy(Data, planeInfo.Data, 0, (int)((width * (planeInfo.Height - 1)) + (planeInfo.Width * planeInfo.PixelStride) - 1));
}
else
{
Marshal.Copy(Data, planeInfo.Data, 0, (int)((width * (planeInfo.Height - 1)) + (planeInfo.Width * planeInfo.PixelStride)));
}
if (planeInfo.Stride != 0)
{
planeInfo.Size = planeInfo.Stride * planeInfo.Height;
}
}
return planeInfo;
}
}
///
/// Captured output
///
[StructLayout(LayoutKind.Sequential)]
public struct MLCameraOutput
{
///
/// version contains the version number for this structure.
///
public uint Version;
///
/// Number of output image planes:
/// - 1 for compressed output such as JPEG stream,
/// - 3 for separate color component output such as YUV/YCbCr/RGB.
///
public byte PlaneCount;
///
/// Output image plane info.
/// The number of output planes is specified by PlaneCount.
///
[MarshalAs(UnmanagedType.ByValArray, SizeConst = NativeBindings.MLCameraMaxImagePlanes)]
public MLCameraPlaneInfo[] Planes;
///
/// Supported output format specified by MLCamera.OutputFormat
///
public MLCamera.OutputFormat Format;
///
/// Create and return an initialized version of this struct.
///
/// Returns a new MLCamera.Output structure.
public static MLCameraOutput Create()
{
return new MLCameraOutput
{
Version = 0,
PlaneCount = 0,
Planes = Enumerable.Repeat(MLCameraPlaneInfo.Create(), NativeBindings.MLCameraMaxImagePlanes).ToArray(),
Format = MLCamera.OutputFormat.JPEG
};
}
public MLCamera.CameraOutput CreateFrameInfo(bool copyToManagedMemory, byte[][] byteArraysToUse = null)
{
var frameInfo = new MLCamera.CameraOutput()
{
Planes = new MLCamera.PlaneInfo[this.PlaneCount],
Format = this.Format
};
for (int i = 0; i < this.PlaneCount; ++i)
{
frameInfo.Planes[i] = Planes[i].CreatePlaneInfo(copyToManagedMemory, byteArraysToUse?[i]);
}
return frameInfo;
}
}
///
/// IntrinsicCalibrationParameters is a structure to provide instrisic calibration information
///
[StructLayout(LayoutKind.Sequential)]
public readonly struct MLCameraIntrinsicCalibrationParameters
{
///
/// version contains the version number for this structure.
///
public readonly uint Version;
///
/// Camera width.
///
public readonly uint Width;
///
/// Camera height.
///
public readonly uint Height;
///
/// Camera focal length.
///
public readonly MLVec2f FocalLength;
///
/// Camera principal point.
///
public readonly MLVec2f PrincipalPoint;
///
/// Field of view in degrees
///
public readonly float FOV;
///
/// Distortion vector.
/// The distortion co-efficients are in the following order:
/// [k1, k2, p1, p2, k3]
///
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MLCameraMaxDistortionCoefficients)]
public readonly double[] Distortion;
}
///
/// ResultExtras is a structure to encapsulate various indices for a capture result.
///
[StructLayout(LayoutKind.Sequential)]
public readonly struct MLCameraResultExtras
{
///
/// version contains the version number for this structure.
///
public readonly uint Version;
///
/// A 64bit integer to index the frame number associated with this result
///
public readonly long FrameNumber;
///
/// VCam exposure timestamp in microseconds (us)
///
public readonly long VcamTimestamp;
///
/// Camera intrinsic parameter.
/// Only valid within callback scope.
/// The Library allocates and maintains the lifetime of intrinsics.
/// Only valid for on_image_buffer_available, on_video_buffer_available, on_preview_buffer_available callbacks.
/// NULL for on_capture_completed, on_capture_failed callbacks
public readonly IntPtr Intrinsics;
}
[StructLayout(LayoutKind.Sequential)]
public readonly struct MLCameraDeviceAvailabilityInfo
{
public readonly MLCamera.Identifier CamId;
public readonly IntPtr UserData;
}
///
/// Device availability status callbacks to be implemented by client to receive device availability status.
///
[StructLayout(LayoutKind.Sequential)]
public struct MLCameraDeviceAvailabilityStatusCallbacks
{
///
/// Version contains the version number for this structure.
///
public uint Version;
///
/// Callback is invoked when the camera becomes available.
///
public DeviceAvailabilityStatusDelegate OnDeviceAvailable;
///
/// Callback is invoked when the camera becomes unavailable.
///
public DeviceAvailabilityStatusDelegate OnDeviceUnavailable;
///
/// Create and return an initialized version of this struct.
///
/// A new instance of this struct.
public static MLCameraDeviceAvailabilityStatusCallbacks Create()
{
return new MLCameraDeviceAvailabilityStatusCallbacks()
{
Version = 1,
OnDeviceAvailable = OnDeviceAvailableCallback,
OnDeviceUnavailable = OnDeviceUnavailableCallback
};
}
public static MLCameraDeviceAvailabilityStatusCallbacks CreateUninitialized()
{
return new MLCameraDeviceAvailabilityStatusCallbacks()
{
Version = 1,
OnDeviceAvailable = null,
OnDeviceUnavailable = null
};
}
}
///
/// Device status callbacks to be implemented by client to receive device status if callback mechanism is used.
///
[StructLayout(LayoutKind.Sequential)]
public struct MLCameraDeviceStatusCallbacks
{
///
/// Version contains the version number for this structure.
///
public uint Version;
///
/// Callback is invoked when the camera is streaming.
///
public OnDeviceStreamingDelegate OnDeviceStreaming;
///
/// Callback is invoked when the camera stops streaming.
///
public OnDeviceIdleDelegate OnDeviceIdle;
///
/// Callback is invoked when the camera is disconnected.
///
public OnDeviceDisconnectedDelegate OnDeviceDisconnected;
///
/// Callback is invoked when the camera encountered errors. Invalid: The camera device is not available. Disabled: The
/// camera device can't be opened due to a device policy. Device error: The camera device encountered a fatal error such as
/// the Lightwear device has lost connection or the hardware comm bus is busy and not be able to response and caused a
/// timeout. Service error: The camera service has encountered a fatal error and could not provide service. Capture failed: The
/// capure request has failed. on_capture_failed or on_capture_buffer_lost callbacks will be invoked when this error
/// happens.
///
public OnDeviceErrorDelegate OnDeviceError;
///
/// Create and return an initialized version of this struct.
///
/// A new instance of this struct.
public static MLCameraDeviceStatusCallbacks Create()
{
return new MLCameraDeviceStatusCallbacks()
{
Version = 1,
OnDeviceStreaming = OnDeviceStreamingCallback,
OnDeviceIdle = OnDeviceIdleCallback,
OnDeviceDisconnected = OnDeviceDisconnectCallback,
OnDeviceError = OnDeviceErrorCallback
};
}
}
///
/// Capture callbacks to be implemented by client to receive capture status if callback mechanism is used. This structure
/// must be initialized by calling MLCameraCaptureCallbacksInit() before use.
///
[StructLayout(LayoutKind.Sequential)]
public struct MLCameraCaptureCallbacks
{
///
/// version contains the version number for this structure.
///
public uint Version;
///
/// Callback is invoked when a capture has failed when the camera device failed to produce a capture result for the request.
///
public OnCaptureFailedDelegate OnCaptureFailed;
///
/// Callback is invoked when an ongoing video or preview capture or both are aborted due to an error.
///
public OnCaptureAbortedDelegate OnCaptureAborted;
///
/// Callback is invoked when capturing single frame is completed and result is available.
///
public OnCaptureCompletedDelegate OnCaptureCompleted;
///
/// Callback is invoked when a captured image buffer is available with #MLCameraCaptureType_ImageRaw.
///
public OnImageBufferAvailableDelegate OnImageBufferAvailable;
///
/// Callback is invoked when a captured raw/compressed video frame buffer is available with #MLCameraCaptureType_VideoRaw.
///
public OnVideoBufferAvailableDelegate OnVideoBufferAvailable;
///
/// Callback is invoked when a preview video frame buffer is available with #MLCameraCaptureType_Preview.
///
public OnPreviewBufferAvailableDelegate OnPreviewBufferAvailable;
///
/// Create and return an initialized version of this struct.
///
/// A new instance of this struct.
public static MLCameraCaptureCallbacks Create()
{
return new MLCameraCaptureCallbacks()
{
Version = 1,
OnCaptureFailed = OnCaptureFailCallback,
OnCaptureAborted = OnCaptureAbortCallback,
OnCaptureCompleted = OnCaptureCompleteCallback,
OnImageBufferAvailable = OnImageBufferAvailableCallback,
OnVideoBufferAvailable = OnVideoBufferAvailableCallback,
OnPreviewBufferAvailable = OnPreviewBufferAvailableCallback
};
}
}
}
}
}