diff --git a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/External/StructArray.cs b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/External/StructArray.cs new file mode 100644 index 000000000..8efc28ee1 --- /dev/null +++ b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/External/StructArray.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace Mediapipe +{ + [StructLayout(LayoutKind.Sequential)] + internal readonly struct StructArray + { + private readonly IntPtr _data; + private readonly int _size; + + public void Dispose() + { + UnsafeNativeMethods.delete_array__Pf(_data); + } + + public List Copy() where T : unmanaged + { + var data = new List(_size); + + CopyTo(data); + return data; + } + + public void CopyTo(List data) where T : unmanaged + { + data.Clear(); + + unsafe + { + var ptr = (T*)_data; + + for (var i = 0; i < _size; i++) + { + data.Add(*ptr++); + } + } + } + } +} diff --git a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/External/StructArray.cs.meta b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/External/StructArray.cs.meta new file mode 100644 index 000000000..d85369370 --- /dev/null +++ b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/External/StructArray.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d8ce195f36f8b3d2cab3e50f079b6507 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Framework/Packet.cs b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Framework/Packet.cs index 29415daed..dbc814415 100644 --- a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Framework/Packet.cs +++ b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Framework/Packet.cs @@ -5,6 +5,7 @@ // https://opensource.org/licenses/MIT. using System; +using System.Collections.Generic; namespace Mediapipe { @@ -43,6 +44,9 @@ internal static Packet CreateEmpty() /// public static Packet CreateForReference(IntPtr ptr) => new Packet(ptr, false); + /// + /// Create a bool Packet from a boolean. + /// public static Packet CreateBool(bool value) { UnsafeNativeMethods.mp__MakeBoolPacket__b(value, out var ptr).Assert(); @@ -50,6 +54,12 @@ public static Packet CreateBool(bool value) return new Packet(ptr, true); } + /// + /// Create a bool Packet. + /// + /// + /// The timestamp of the packet. + /// public static Packet CreateBoolAt(bool value, long timestampMicrosec) { UnsafeNativeMethods.mp__MakeBoolPacket_At__b_ll(value, timestampMicrosec, out var ptr).Assert(); @@ -57,6 +67,29 @@ public static Packet CreateBoolAt(bool value, long timestampMicrosec) return new Packet(ptr, true); } + /// + /// Create a bool vector Packet. + /// + public static Packet CreateBoolVector(bool[] value) + { + UnsafeNativeMethods.mp__MakeBoolVectorPacket__Pb_i(value, value.Length, out var ptr).Assert(); + + return new Packet(ptr, true); + } + + /// + /// Create a bool vector Packet. + /// + /// + /// The timestamp of the packet. + /// + public static Packet CreateBoolVectorAt(bool[] value, long timestampMicrosec) + { + UnsafeNativeMethods.mp__MakeBoolVectorPacket_At__Pb_i_ll(value, value.Length, timestampMicrosec, out var ptr).Assert(); + + return new Packet(ptr, true); + } + /// /// Get the content of the as a boolean. /// @@ -74,6 +107,32 @@ public bool GetBool() return value; } + /// + /// Get the content of a bool vector Packet as a . + /// + public List GetBoolList() + { + var value = new List(); + GetBoolList(value); + + return value; + } + + /// + /// Get the content of a bool vector Packet as a . + /// + /// + /// The to be filled with the content of the . + /// + public void GetBoolList(List value) + { + UnsafeNativeMethods.mp_Packet__GetBoolVector(mpPtr, out var structArray).Assert(); + GC.KeepAlive(this); + + structArray.CopyTo(value); + structArray.Dispose(); + } + /// /// Validate if the content of the is a boolean. /// @@ -87,5 +146,19 @@ public void ValidateAsBool() GC.KeepAlive(this); AssertStatusOk(statusPtr); } + + /// + /// Validate if the content of the is a std::vector<bool>. + /// + /// + /// If the doesn't contain std::vector<bool>. + /// + public void ValidateAsBoolVector() + { + UnsafeNativeMethods.mp_Packet__ValidateAsBoolVector(mpPtr, out var statusPtr).Assert(); + + GC.KeepAlive(this); + AssertStatusOk(statusPtr); + } } } diff --git a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/PInvoke/NativeMethods/Framework/Packet_Unsafe.cs b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/PInvoke/NativeMethods/Framework/Packet_Unsafe.cs index 0b74abb19..0b94c0d13 100644 --- a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/PInvoke/NativeMethods/Framework/Packet_Unsafe.cs +++ b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/PInvoke/NativeMethods/Framework/Packet_Unsafe.cs @@ -54,6 +54,20 @@ internal static partial class UnsafeNativeMethods public static extern MpReturnCode mp_Packet__ValidateAsBool(IntPtr packet, out IntPtr status); #endregion + #region BoolVector + [DllImport(MediaPipeLibrary, ExactSpelling = true)] + public static extern MpReturnCode mp__MakeBoolVectorPacket__Pb_i(bool[] value, int size, out IntPtr packet); + + [DllImport(MediaPipeLibrary, ExactSpelling = true)] + public static extern MpReturnCode mp__MakeBoolVectorPacket_At__Pb_i_ll(bool[] value, int size, long timestampMicrosec, out IntPtr packet); + + [DllImport(MediaPipeLibrary, ExactSpelling = true)] + public static extern MpReturnCode mp_Packet__GetBoolVector(IntPtr packet, out StructArray value); + + [DllImport(MediaPipeLibrary, ExactSpelling = true)] + public static extern MpReturnCode mp_Packet__ValidateAsBoolVector(IntPtr packet, out IntPtr status); + #endregion + #region Float [DllImport(MediaPipeLibrary, ExactSpelling = true)] public static extern MpReturnCode mp__MakeFloatPacket__f(float value, out IntPtr packet); diff --git a/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/PacketTest.cs b/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/PacketTest.cs index 87c131808..dcc298203 100644 --- a/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/PacketTest.cs +++ b/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/PacketTest.cs @@ -37,6 +37,45 @@ public void CreateBoolAt_ShouldReturnNewBoolPacket(bool value) } #endregion + #region BoolVector + [Test] + public void CreateBoolVector_ShouldReturnNewBoolVectorPacket() + { + var value = new bool[] { true, false }; + using var packet = Packet.CreateBoolVector(value); + + Assert.DoesNotThrow(packet.ValidateAsBoolVector); + + var result = packet.GetBoolList(); + Assert.AreEqual(value.Length, result.Count); + for (var i = 0; i < value.Length; i++) + { + Assert.AreEqual(value[i], result[i]); + } + + using var unsetTimestamp = Timestamp.Unset(); + Assert.AreEqual(unsetTimestamp.Microseconds(), packet.TimestampMicroseconds()); + } + + [Test] + public void CreateBoolVectorAt_ShouldReturnNewBoolVectorPacket() + { + var value = new bool[] { true, false }; + var timestamp = 1; + using var packet = Packet.CreateBoolVectorAt(value, timestamp); + + Assert.DoesNotThrow(packet.ValidateAsBoolVector); + + var result = packet.GetBoolList(); + Assert.AreEqual(value.Length, result.Count); + for (var i = 0; i < value.Length; i++) + { + Assert.AreEqual(value[i], result[i]); + } + Assert.AreEqual(timestamp, packet.TimestampMicroseconds()); + } + #endregion + #region #Validate [Test] public void ValidateAsBool_ShouldThrow_When_ValueIsNotSet() @@ -44,6 +83,13 @@ public void ValidateAsBool_ShouldThrow_When_ValueIsNotSet() using var packet = Packet.CreateEmpty(); _ = Assert.Throws(packet.ValidateAsBool); } + + [Test] + public void ValidateAsBoolVector_ShouldThrow_When_ValueIsNotSet() + { + using var packet = Packet.CreateEmpty(); + _ = Assert.Throws(packet.ValidateAsBoolVector); + } #endregion } } diff --git a/mediapipe_api/framework/packet.cc b/mediapipe_api/framework/packet.cc index 31745ad79..49319eb3c 100644 --- a/mediapipe_api/framework/packet.cc +++ b/mediapipe_api/framework/packet.cc @@ -103,6 +103,26 @@ MpReturnCode mp_Packet__ValidateAsBool(mediapipe::Packet* packet, absl::Status** CATCH_EXCEPTION } +// BoolVectorPacket +MpReturnCode mp__MakeBoolVectorPacket__Pb_i(bool* value, int size, mediapipe::Packet** packet_out) { + return mp__MakeVectorPacket(value, size, packet_out); +} + +MpReturnCode mp__MakeBoolVectorPacket_At__Pb_i_ll(bool* value, int size, int64 timestampMicrosec, mediapipe::Packet** packet_out) { + return mp__MakeVectorPacket_At(value, size, timestampMicrosec, packet_out); +} + +MpReturnCode mp_Packet__GetBoolVector(mediapipe::Packet* packet, mp_api::StructArray* value_out) { + return mp_Packet__GetStructVector(packet, value_out); +} + +MpReturnCode mp_Packet__ValidateAsBoolVector(mediapipe::Packet* packet, absl::Status** status_out) { + TRY + *status_out = new absl::Status{packet->ValidateAsType>()}; + RETURN_CODE(MpReturnCode::Success); + CATCH_EXCEPTION +} + // FloatPacket MpReturnCode mp__MakeFloatPacket__f(float value, mediapipe::Packet** packet_out) { TRY diff --git a/mediapipe_api/framework/packet.h b/mediapipe_api/framework/packet.h index 48df4fbe5..3b3f37104 100644 --- a/mediapipe_api/framework/packet.h +++ b/mediapipe_api/framework/packet.h @@ -52,6 +52,12 @@ MP_CAPI(MpReturnCode) mp__MakeBoolPacket_At__b_ll(bool value, int64 timestampMic MP_CAPI(MpReturnCode) mp_Packet__GetBool(mediapipe::Packet* packet, bool* value_out); MP_CAPI(MpReturnCode) mp_Packet__ValidateAsBool(mediapipe::Packet* packet, absl::Status** status_out); +// std::vector +MP_CAPI(MpReturnCode) mp__MakeBoolVectorPacket__Pb_i(bool* value, int size, mediapipe::Packet** packet_out); +MP_CAPI(MpReturnCode) mp__MakeBoolVectorPacket_At__Pb_i_ll(bool* value, int size, int64 timestampMicrosec, mediapipe::Packet** packet_out); +MP_CAPI(MpReturnCode) mp_Packet__GetBoolVector(mediapipe::Packet* packet, mp_api::StructArray* value_out); +MP_CAPI(MpReturnCode) mp_Packet__ValidateAsBoolVector(mediapipe::Packet* packet, absl::Status** status_out); + // float MP_CAPI(MpReturnCode) mp__MakeFloatPacket__f(float value, mediapipe::Packet** packet_out); MP_CAPI(MpReturnCode) mp__MakeFloatPacket_At__f_Rt(float value, mediapipe::Timestamp* timestamp, mediapipe::Packet** packet_out); @@ -146,6 +152,15 @@ inline MpReturnCode mp__MakeVectorPacket_At(const T* array, int size, mediapipe: CATCH_EXCEPTION } +template +inline MpReturnCode mp__MakeVectorPacket_At(const T* array, int size, int64 timestampMicrosec, mediapipe::Packet** packet_out) { + TRY + std::vector vector(array, array + size); + *packet_out = new mediapipe::Packet{mediapipe::MakePacket>(vector).At(mediapipe::Timestamp(timestampMicrosec))}; + RETURN_CODE(MpReturnCode::Success); + CATCH_EXCEPTION +} + template inline MpReturnCode mp_Packet__GetStructVector(mediapipe::Packet* packet, mp_api::StructArray* value_out) { TRY_ALL