Skip to content

Commit

Permalink
Fix deleter (#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
Speykious authored Mar 4, 2022
1 parent 9dcb9c3 commit ec44eb0
Showing 1 changed file with 27 additions and 8 deletions.
35 changes: 27 additions & 8 deletions Mediapipe.Net/Framework/Format/ImageFrame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// MediaPipe.NET is licensed under the MIT License. See LICENSE for details.

using System;
using System.Runtime.InteropServices;
using Mediapipe.Net.Core;
using Mediapipe.Net.Native;

Expand All @@ -14,6 +15,8 @@ public unsafe class ImageFrame : MpResourceHandle
public static readonly uint GlDefaultAlignmentBoundary = 4;

public delegate void Deleter(void* ptr);
private readonly Deleter? deleter;
private GCHandle? deleterHandle;

public ImageFrame() : base()
{
Expand All @@ -39,35 +42,51 @@ public ImageFrame(ImageFormat format, int width, int height, uint alignmentBound
// mediapipe::ImageFormat::Format format,
// int width, int height, int width_step, uint8* pixel_data,
// Deleter* deleter, mediapipe::ImageFrame** image_frame_out);
unsafe public ImageFrame(ImageFormat format, int width, int height, int widthStep, byte* pixelData) : base()
public unsafe ImageFrame(ImageFormat format, int width, int height, int widthStep, byte* pixelData) : base()
{
deleter = new Deleter(releasePixelData);
deleterHandle = GCHandle.Alloc(deleter);

UnsafeNativeMethods.mp_ImageFrame__ui_i_i_i_Pui8_PF(
format, width, height, widthStep,
pixelData,
releasePixelData,
deleter,
out var ptr).Assert();
Ptr = ptr;
}

public ImageFrame(ImageFormat format, int width, int height, int widthStep, ReadOnlySpan<byte> pixelData)
: this(format, width, height, widthStep, spanToBytePtr(pixelData)) { }

private static byte* spanToBytePtr(ReadOnlySpan<byte> span)
{
fixed (byte* ptr = span)
deleter = releasePixelData;
deleterHandle = GCHandle.Alloc(deleter);

fixed (byte* pixelDataPtr = pixelData)
{
return ptr;
UnsafeNativeMethods.mp_ImageFrame__ui_i_i_i_Pui8_PF(
format, width, height, widthStep,
pixelDataPtr,
deleter,
out var ptr).Assert();
Ptr = ptr;
}
}

protected override void DeleteMpPtr() => UnsafeNativeMethods.mp_ImageFrame__delete(Ptr);

// [AOT.MonoPInvokeCallback(typeof(Deleter))] (?)
private static void releasePixelData(void* ptr)
{
// Do nothing (pixelData is moved)
}

protected override void DisposeUnmanaged()
{
base.DisposeUnmanaged();

// `deleter` must not be garbage collected until unmanaged code calls it.
if (deleterHandle is GCHandle handle && handle.IsAllocated)
handle.Free();
}

public bool IsEmpty => SafeNativeMethods.mp_ImageFrame__IsEmpty(MpPtr) > 0;

public bool IsContiguous => SafeNativeMethods.mp_ImageFrame__IsContiguous(MpPtr) > 0;
Expand Down

0 comments on commit ec44eb0

Please sign in to comment.