private readonly NativeHandles.HandleWrapper <NativeHandles.PlaybackHandle> handle; // This class is an wrapper around this handle /// <summary>Opens an existing recording file for reading.</summary> /// <param name="filePath">File system path of the existing recording. Not <see langword="null"/>. Not empty.</param> /// <exception cref="ArgumentNullException"><paramref name="filePath"/> is null or empty.</exception> /// <exception cref="ArgumentException"><paramref name="filePath"/> contains some invalid character. Also, right now non-Latin letters are not supported in <paramref name="filePath"/> under Windows.</exception> /// <exception cref="FileNotFoundException">Files specified in <paramref name="filePath"/> does not exist.</exception> /// <exception cref="PlaybackException">Cannot open file specified in <paramref name="filePath"/> for playback. See logs for details.</exception> public Playback(string filePath) { if (string.IsNullOrWhiteSpace(filePath)) { throw new ArgumentNullException(nameof(filePath)); } if (filePath.IndexOfAny(Path.GetInvalidPathChars()) >= 0) { throw new ArgumentException($"Path \"{filePath}\" contains invalid characters.", nameof(filePath)); } if (!File.Exists(filePath)) { throw new FileNotFoundException($"Cannot find file \"{filePath}\".", filePath); } var pathAsBytes = Helpers.FilePathNameToBytes(filePath); var res = NativeApi.PlaybackOpen(pathAsBytes, out var handle); if (res != NativeCallResults.Result.Succeeded || handle == null || handle.IsInvalid) { throw new PlaybackException($"Cannot open file \"{filePath}\" for playback.", filePath); } this.handle = handle; this.handle.Disposed += Handle_Disposed; FilePath = filePath; }
/// <summary>Creates a body tracker.</summary> /// <param name="calibration">The sensor calibration that will be used for capture processing.</param> /// <param name="config">The configuration we want to run the tracker in. This can be initialized with <see cref="TrackerConfiguration.Default"/>.</param> /// <remarks><para> /// Under the hood Body Tracking runtime will be initialized during the first call of this constructor. /// It is rather time consuming operation: initialization of ONNX runtime, loading and parsing of neural network model, etc. /// For this reason, it is recommended to initialize Body Tracking runtime in advance: <see cref="Sdk.TryInitializeBodyTrackingRuntime(out string)"/>. /// </para><para> /// Also, Body Tracking runtime must be available in one of the following locations: /// directory with executable file, /// directory with <c>K4AdotNet</c> assembly, /// installation directory of Body Tracking SDK under <c>Program Files</c>. /// </para></remarks> /// <exception cref="ArgumentOutOfRangeException"> /// Invalid value of <paramref name="calibration"/>: <see cref="Calibration.DepthMode"/> cannot be <see cref="DepthMode.Off"/> and <see cref="DepthMode.PassiveIR"/>. /// Because depth data is required for body tracking. /// </exception> /// <exception cref="NotSupportedException"> /// Only one tracker is allowed to exist at the same time in each process. If you call this constructor without destroying the /// previous tracker you created, the constructor call will fail with this exception. /// </exception> /// <exception cref="BodyTrackingException"> /// Unable to find/initialize Body Tracking runtime. /// </exception> /// <seealso cref="Sdk.IsBodyTrackingRuntimeAvailable(out string)"/> /// <seealso cref="Sdk.TryInitializeBodyTrackingRuntime(out string)"/> public Tracker(ref Calibration calibration, TrackerConfiguration config = default(TrackerConfiguration)) { if (!calibration.DepthMode.HasDepth()) { throw new ArgumentOutOfRangeException(nameof(calibration) + "." + nameof(calibration.DepthMode)); } DepthMode = calibration.DepthMode; var incrementedInstanceCounter = Interlocked.Increment(ref instancesCounter); try { if (incrementedInstanceCounter != 1) { throw new NotSupportedException("Oops! Current version of Body Tracking runtime does not support creation of multiple body trackers. Sorry!"); } if (!Sdk.TryCreateTrackerHandle(ref calibration, config, out var handle, out var message)) { throw new BodyTrackingException(message); } this.handle = handle; this.handle.Disposed += Handle_Disposed; } catch { Interlocked.Decrement(ref instancesCounter); throw; } }
// Don't use this method to create image with unknown/unspecified stride (like MJPEG). // For such formats, size of image in bytes must be specified to create image. public Image(ImageFormat format, int widthPixels, int heightPixels, int strideBytes) { if (widthPixels <= 0) { throw new ArgumentOutOfRangeException(nameof(widthPixels)); } if (heightPixels <= 0) { throw new ArgumentOutOfRangeException(nameof(heightPixels)); } if (strideBytes < 0) { throw new ArgumentOutOfRangeException(nameof(strideBytes)); } if (strideBytes == 0) { throw new InvalidOperationException("Zero stride is used for formats without complex structure like MJPEG. In this case size of image in bytes must be specified to create image."); } if (format.HasKnownBytesPerPixel() && strideBytes < widthPixels * format.BytesPerPixel()) { throw new ArgumentOutOfRangeException(nameof(strideBytes)); } var res = NativeApi.ImageCreate(format, widthPixels, heightPixels, strideBytes, out var handle); if (res != NativeCallResults.Result.Succeeded || handle == null || handle.IsInvalid) { throw new ArgumentException($"Cannot create image with format {format}, size {widthPixels}x{heightPixels} pixels and stride {strideBytes} bytes."); } this.handle = handle; this.handle.Disposed += Handle_Disposed; }
private Device(NativeHandles.DeviceHandle handle, string serialNumber, HardwareVersion version) { this.handle = handle; this.handle.Disposed += Handle_Disposed; SerialNumber = serialNumber; Version = version; }
public Recorder(string filePath, Sensor.Device device, Sensor.DeviceConfiguration config) { if (string.IsNullOrWhiteSpace(filePath)) { throw new ArgumentNullException(nameof(filePath)); } if (filePath.IndexOfAny(Path.GetInvalidPathChars()) >= 0) { throw new ArgumentException($"Path \"{filePath}\" contains invalid characters.", nameof(filePath)); } var pathAsBytes = Helpers.FilePathNameToBytes(filePath); var res = NativeApi.RecordCreate(pathAsBytes, Sensor.Device.ToHandle(device), config, out var handle); if (res != NativeCallResults.Result.Succeeded || handle == null || handle.IsInvalid) { throw new RecordingException($"Cannot initialize recording to file \"{filePath}\"."); } this.handle = handle; this.handle.Disposed += Handle_Disposed; FilePath = filePath; }
private readonly NativeHandles.HandleWrapper <NativeHandles.CaptureHandle> handle; // this class is an wrapper around this handle /// <summary>Creates an empty capture object.</summary> /// <exception cref="InvalidOperationException"> /// Sensor SDK fails to create empty capture object for some reason. For details see logs. /// </exception> public Capture() { var res = NativeApi.CaptureCreate(out var handle); if (res != NativeCallResults.Result.Succeeded || handle == null || handle.IsInvalid) { throw new InvalidOperationException("Failed to create blank capture instance"); } this.handle = handle; this.handle.Disposed += Handle_Disposed; }
public Transformation(ref Calibration calibration) { var handle = NativeApi.TransformationCreate(ref calibration); if (handle == null || handle.IsInvalid) { throw new ArgumentException("Cannot create transformation object from specified calibration data (or depthengine_1_0.dll library cannot be found).", nameof(calibration)); } this.handle = handle; this.handle.Disposed += Handle_Disposed; DepthMode = calibration.DepthMode; ColorResolution = calibration.ColorResolution; }
public Tracker(ref Sensor.Calibration calibration) { if (Interlocked.Increment(ref instancesCounter) != 1) { Interlocked.Decrement(ref instancesCounter); throw new NotSupportedException("Oops! Current version of Body Tracking SDK does not support creation of multiple body tracker. Sorry!"); } if (NativeApi.TrackerCreate(ref calibration, out var handle) != NativeCallResults.Result.Succeeded || handle == null || handle.IsInvalid) throw new BodyTrackingException("Cannot initialize body tracking infrastructure"); this.handle = handle; this.handle.Disposed += Handle_Disposed; }
/// <summary> /// Creates transformation object for a give calibration data. /// </summary> /// <param name="calibration">Camera calibration data.</param> /// <remarks><para> /// Each transformation instance requires some pre-computed resources to be allocated, /// which are retained until the call of <see cref="Dispose"/> method. /// </para><para> /// <see cref="Sdk.DEPTHENGINE_DLL_NAME"/> library is required for this functionality. /// </para></remarks> /// <exception cref="InvalidOperationException">Something wrong with calibration data or <see cref="Sdk.DEPTHENGINE_DLL_NAME"/> library cannot be loaded.</exception> /// <seealso cref="Dispose"/> public Transformation(ref Calibration calibration) { var handle = NativeApi.TransformationCreate(ref calibration); if (handle == null || handle.IsInvalid) { throw new InvalidOperationException( $"Cannot create transformation object from specified calibration data or {Sdk.DEPTHENGINE_DLL_NAME} library cannot be found)."); } this.handle = handle; this.handle.Disposed += Handle_Disposed; DepthMode = calibration.DepthMode; ColorResolution = calibration.ColorResolution; }
/// <summary>Creates a body tracker.</summary> /// <param name="calibration">The sensor calibration that will be used for capture processing.</param> /// <param name="config">The configuration we want to run the tracker in. This can be initialized with <see cref="TrackerConfiguration.Default"/>.</param> /// <remarks><para> /// Under the hood Body Tracking runtime will be initialized during the first call of this constructor. /// It is rather time consuming operation: initialization of ONNX runtime, loading and parsing of neural network model, etc. /// For this reason, it is recommended to initialize Body Tracking runtime in advance: <see cref="Sdk.TryInitializeBodyTrackingRuntime(out string)"/>. /// </para><para> /// Also, Body Tracking runtime must be available in one of the following locations: /// directory with executable file, /// directory with <c>K4AdotNet</c> assembly, /// installation directory of Body Tracking SDK under <c>Program Files</c>. /// </para></remarks> /// <exception cref="ArgumentOutOfRangeException"> /// Invalid value of <paramref name="calibration"/>: <see cref="Calibration.DepthMode"/> cannot be <see cref="DepthMode.Off"/> and <see cref="DepthMode.PassiveIR"/>. /// Because depth data is required for body tracking. /// </exception> /// <exception cref="BodyTrackingException"> /// Unable to find/initialize Body Tracking runtime. /// </exception> /// <seealso cref="Sdk.IsBodyTrackingRuntimeAvailable(out string)"/> /// <seealso cref="Sdk.TryInitializeBodyTrackingRuntime(out string)"/> public Tracker(ref Calibration calibration, TrackerConfiguration config = default) { if (!calibration.DepthMode.HasDepth()) { throw new ArgumentOutOfRangeException(nameof(calibration) + "." + nameof(calibration.DepthMode)); } DepthMode = calibration.DepthMode; if (!Sdk.TryCreateTrackerHandle(ref calibration, config, out var handle, out var message)) { throw new BodyTrackingException(message); } this.handle = handle; this.handle.Disposed += Handle_Disposed; }
/// <summary>Creates new image with specified format, size in pixels and stride in bytes.</summary> /// <param name="format">Format of image. Must be format with known stride: <see cref="ImageFormats.StrideBytes(ImageFormat, int)"/>.</param> /// <param name="widthPixels">Width of image in pixels. Must be positive.</param> /// <param name="heightPixels">Height of image in pixels. Must be positive.</param> /// <param name="strideBytes">Image stride in bytes (the number of bytes per horizontal line of the image). Must be non-negative. Zero value can be used for <see cref="ImageFormat.ColorMjpg"/> and <see cref="ImageFormat.Custom"/>.</param> /// <param name="sizeBytes">Size of image buffer in size. Non negative. Cannot be less than size calculated from image parameters.</param> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="widthPixels"/> or <paramref name="heightPixels"/> is equal to or less than zero /// or <paramref name="strideBytes"/> is less than zero or <paramref name="strideBytes"/> is too small for specified <paramref name="format"/> /// or <paramref name="sizeBytes"/> is less than zero or <paramref name="sizeBytes"/> is less than size calculated from <paramref name="heightPixels"/> and <paramref name="strideBytes"/>. /// </exception> /// <exception cref="InvalidOperationException"> /// <paramref name="strideBytes"/> is equal to zero. In this case size of image in bytes must be specified to create image. /// </exception> public Image(ImageFormat format, int widthPixels, int heightPixels, int strideBytes, int sizeBytes) { if (widthPixels <= 0) { throw new ArgumentOutOfRangeException(nameof(widthPixels)); } if (heightPixels <= 0) { throw new ArgumentOutOfRangeException(nameof(heightPixels)); } if (strideBytes < 0) { throw new ArgumentOutOfRangeException(nameof(strideBytes)); } if (format.HasKnownBytesPerPixel() && strideBytes < widthPixels * format.BytesPerPixel()) { throw new ArgumentOutOfRangeException(nameof(strideBytes)); } if (sizeBytes <= 0) { throw new ArgumentOutOfRangeException(nameof(sizeBytes)); } if (strideBytes > 0 && sizeBytes < format.ImageSizeBytes(strideBytes, heightPixels)) { throw new ArgumentOutOfRangeException(nameof(sizeBytes)); } var buffer = Marshal.AllocHGlobal(sizeBytes); if (buffer == IntPtr.Zero) { throw new OutOfMemoryException($"Cannot allocate buffer of {sizeBytes} bytes."); } var res = NativeApi.ImageCreateFromBuffer(format, widthPixels, heightPixels, strideBytes, buffer, Helpers.Int32ToUIntPtr(sizeBytes), unmanagedBufferReleaseCallback, IntPtr.Zero, out var handle); if (res != NativeCallResults.Result.Succeeded || handle == null || handle.IsInvalid) { throw new ArgumentException($"Cannot create image with format {format}, size {widthPixels}x{heightPixels} pixels, stride {strideBytes} bytes from buffer of size {sizeBytes} bytes."); } this.handle = handle; this.handle.Disposed += Handle_Disposed; }
/// <summary>Creates new image with specified format, size in pixels and stride in bytes.</summary> /// <param name="format">Format of image. Must be format with known stride: <see cref="ImageFormats.StrideBytes(ImageFormat, int)"/>.</param> /// <param name="widthPixels">Width of image in pixels. Must be positive.</param> /// <param name="heightPixels">Height of image in pixels. Must be positive.</param> /// <param name="strideBytes">Image stride in bytes (the number of bytes per horizontal line of the image). Must be positive.</param> /// <remarks> /// Don't use this method to create image with unknown/unspecified stride (like MJPEG). /// For such formats, size of image in bytes must be specified to create image: <see cref="Image.Image(ImageFormat, int, int, int, int)"/>. /// </remarks> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="widthPixels"/> or <paramref name="heightPixels"/> is equal to or less than zero /// or <paramref name="strideBytes"/> is less than zero or <paramref name="strideBytes"/> is too small for specified <paramref name="format"/>. /// </exception> /// <exception cref="InvalidOperationException"> /// <paramref name="strideBytes"/> is equal to zero. In this case size of image in bytes must be specified to create image. /// </exception> /// <exception cref="NotSupportedException"> /// If <paramref name="format"/> equals to <see cref="ImageFormat.ColorNV12"/>. /// For details see https://github.com/microsoft/Azure-Kinect-Sensor-SDK/issues/587. /// </exception> public Image(ImageFormat format, int widthPixels, int heightPixels, int strideBytes) { if (widthPixels <= 0) { throw new ArgumentOutOfRangeException(nameof(widthPixels)); } if (heightPixels <= 0) { throw new ArgumentOutOfRangeException(nameof(heightPixels)); } if (strideBytes < 0) { throw new ArgumentOutOfRangeException(nameof(strideBytes)); } if (strideBytes == 0) { throw new InvalidOperationException("Zero stride is used for formats with complex structure like MJPEG. In this case size of image in bytes must be specified to create image."); } if (format.HasKnownBytesPerPixel() && strideBytes < widthPixels * format.BytesPerPixel()) { throw new ArgumentOutOfRangeException(nameof(strideBytes)); } if (format == ImageFormat.ColorNV12) { // Because of bug in Sensor DK // See https://github.com/microsoft/Azure-Kinect-Sensor-SDK/issues/587 throw new NotSupportedException($"Please, specify size of image data in bytes for {format} format. This is because of issue #587 in Sensor DK."); } var res = NativeApi.ImageCreate(format, widthPixels, heightPixels, strideBytes, out var handle); if (res != NativeCallResults.Result.Succeeded || handle == null || handle.IsInvalid) { throw new ArgumentException($"Cannot create image with format {format}, size {widthPixels}x{heightPixels} pixels and stride {strideBytes} bytes."); } this.handle = handle; this.handle.Disposed += Handle_Disposed; }
private readonly NativeHandles.HandleWrapper <NativeHandles.RecordHandle> handle; // This class is an wrapper around this handle /// <summary> /// Opens a new recording file for writing. /// </summary> /// <param name="filePath">File system path for the new recording. Not <see langword="null"/>, not empty.</param> /// <param name="device">The Azure Kinect device that is being recorded. The device is used to store device calibration and serial /// number information. May be <see langword="null"/> if recording user-generated data.</param> /// <param name="config">The configuration the Azure Kinect device was started with. Must be valid: see <see cref="Sensor.DeviceConfiguration.IsValid"/>.</param> /// <remarks><para> /// The file will be created if it doesn't exist, or overwritten if an existing file is specified. /// </para><para> /// Streaming does not need to be started on the device at the time this function is called, but when it is started /// it should be started with the same configuration provided in <paramref name="config"/>. /// </para><para> /// Subsequent calls to <see cref="WriteCapture"/> will need to have images in the resolution and format defined /// in <paramref name="config"/>. /// </para></remarks> /// <exception cref="ArgumentNullException"><paramref name="filePath"/> is null or empty.</exception> /// <exception cref="ArgumentException"><paramref name="config"/> is invalid or <paramref name="filePath"/> contains some invalid character. Also, right now non-Latin letters are not supported in <paramref name="filePath"/> under Windows.</exception> /// <exception cref="NotSupportedException">Color format is not supported for recorded. It is recommended to use <see cref="Sensor.ImageFormat.ColorMjpg"/> for recording.</exception> public Recorder(string filePath, Sensor.Device device, Sensor.DeviceConfiguration config) { if (string.IsNullOrWhiteSpace(filePath)) { throw new ArgumentNullException(nameof(filePath)); } if (filePath.IndexOfAny(Path.GetInvalidPathChars()) >= 0) { throw new ArgumentException($"Path \"{filePath}\" contains invalid characters.", nameof(filePath)); } if (!config.IsValid(out var message)) { throw new ArgumentException(message, nameof(config)); } if (config.ColorFormat == Sensor.ImageFormat.ColorBgra32) { throw new NotSupportedException($"Color format {config.ColorFormat} is not supported for recording. Recommended format: {Sensor.ImageFormat.ColorMjpg}."); } var pathAsBytes = Helpers.FilePathNameToBytes(filePath); var res = NativeApi.RecordCreate(pathAsBytes, Sensor.Device.ToHandle(device), config, out var handle); if (res != NativeCallResults.Result.Succeeded || handle == null || handle.IsInvalid) { throw new RecordingException($"Cannot initialize recording to file \"{filePath}\".", filePath); } this.handle = handle; this.handle.Disposed += Handle_Disposed; FilePath = filePath; DeviceConfiguration = config; CustomTracks = new RecorderCustomTrackCollection(this); }
private readonly NativeHandles.HandleWrapper <NativeHandles.BodyFrameHandle> handle; // this class is an wrapper around this handle private BodyFrame(NativeHandles.BodyFrameHandle handle) { this.handle = handle; this.handle.Disposed += Handle_Disposed; }
private readonly NativeHandles.HandleWrapper <NativeHandles.ImageHandle> handle; // This class is an wrapper around this handle private Image(NativeHandles.ImageHandle handle) { this.handle = handle; this.handle.Disposed += Handle_Disposed; }
private readonly NativeHandles.HandleWrapper <NativeHandles.PlaybackDataBlockHandle> handle; // this class is an wrapper around this handle private PlaybackDataBlock(NativeHandles.PlaybackDataBlockHandle handle) { this.handle = handle; this.handle.Disposed += Handle_Disposed; }
private Capture(NativeHandles.CaptureHandle handle) { this.handle = handle; this.handle.Disposed += Handle_Disposed; }