diff --git a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Framework/Packet/FloatArrayPacket.cs b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Framework/Packet/FloatArrayPacket.cs index 1b7f4bd80..a034a3659 100644 --- a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Framework/Packet/FloatArrayPacket.cs +++ b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Framework/Packet/FloatArrayPacket.cs @@ -64,10 +64,12 @@ public override float[] Get() } var result = new float[length]; + UnsafeNativeMethods.mp_Packet__GetFloatArray_i(mpPtr, length, out var arrayPtr).Assert(); + GC.KeepAlive(this); unsafe { - var src = (float*)GetArrayPtr(); + var src = (float*)arrayPtr; for (var i = 0; i < result.Length; i++) { @@ -75,16 +77,10 @@ public override float[] Get() } } + UnsafeNativeMethods.delete_array__Pf(arrayPtr); return result; } - public IntPtr GetArrayPtr() - { - UnsafeNativeMethods.mp_Packet__GetFloatArray(mpPtr, out var value).Assert(); - GC.KeepAlive(this); - return value; - } - public override StatusOr Consume() { throw new NotSupportedException(); diff --git a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Framework/Packet/FloatVectorPacket.cs b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Framework/Packet/FloatVectorPacket.cs new file mode 100644 index 000000000..648a5057c --- /dev/null +++ b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Framework/Packet/FloatVectorPacket.cs @@ -0,0 +1,108 @@ +// Copyright (c) 2021 homuler +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; + +namespace Mediapipe +{ + [StructLayout(LayoutKind.Sequential)] + internal readonly struct FloatVector + { + private readonly IntPtr _data; + private readonly int _size; + + public void Dispose() + { + UnsafeNativeMethods.delete_array__Pf(_data); + } + + public List Copy() + { + var data = new List(_size); + + unsafe + { + var floatPtr = (float*)_data; + + for (var i = 0; i < _size; i++) + { + data.Add(*floatPtr++); + } + } + return data; + } + } + + public class FloatVectorPacket : Packet> + { + /// + /// Creates an empty instance. + /// + /// + public FloatVectorPacket() : base(true) { } + + [UnityEngine.Scripting.Preserve] + public FloatVectorPacket(IntPtr ptr, bool isOwner = true) : base(ptr, isOwner) { } + + + public FloatVectorPacket(float[] value) : base() + { + UnsafeNativeMethods.mp__MakeFloatVectorPacket__Pf_i(value, value.Length, out var ptr).Assert(); + this.ptr = ptr; + } + + public FloatVectorPacket(float[] value, Timestamp timestamp) : base() + { + UnsafeNativeMethods.mp__MakeFloatVectorPacket_At__Pf_i_Rt(value, value.Length, timestamp.mpPtr, out var ptr).Assert(); + GC.KeepAlive(timestamp); + this.ptr = ptr; + } + + public FloatVectorPacket(List value) : base() + { + UnsafeNativeMethods.mp__MakeFloatVectorPacket__Pf_i(value.ToArray(), value.Count, out var ptr).Assert(); + this.ptr = ptr; + } + + public FloatVectorPacket(List value, Timestamp timestamp) : base() + { + UnsafeNativeMethods.mp__MakeFloatVectorPacket_At__Pf_i_Rt(value.ToArray(), value.Count, timestamp.mpPtr, out var ptr).Assert(); + GC.KeepAlive(timestamp); + this.ptr = ptr; + } + + public FloatVectorPacket At(Timestamp timestamp) + { + return At(timestamp); + } + + public override List Get() + { + UnsafeNativeMethods.mp_Packet__GetFloatVector(mpPtr, out var floatVector).Assert(); + GC.KeepAlive(this); + + var result = floatVector.Copy(); + floatVector.Dispose(); + return result; + } + + public override StatusOr> Consume() + { + throw new NotSupportedException(); + } + + public override Status ValidateAsType() + { + UnsafeNativeMethods.mp_Packet__ValidateAsFloatVector(mpPtr, out var statusPtr).Assert(); + + GC.KeepAlive(this); + return new Status(statusPtr); + } + } +} diff --git a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Framework/Packet/FloatVectorPacket.cs.meta b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Framework/Packet/FloatVectorPacket.cs.meta new file mode 100644 index 000000000..23702bbfb --- /dev/null +++ b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Framework/Packet/FloatVectorPacket.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8a9b77e746fd38d46a09d847f7370446 +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/MatrixPacket.cs b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Framework/Packet/MatrixPacket.cs new file mode 100644 index 000000000..e2f139b29 --- /dev/null +++ b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Framework/Packet/MatrixPacket.cs @@ -0,0 +1,66 @@ +// Copyright (c) 2021 homuler +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. + +using Google.Protobuf; +using System; + +namespace Mediapipe +{ + public class MatrixPacket : Packet + { + /// + /// Creates an empty instance. + /// + public MatrixPacket() : base(true) { } + + [UnityEngine.Scripting.Preserve] + public MatrixPacket(IntPtr ptr, bool isOwner = true) : base(ptr, isOwner) { } + + public MatrixPacket(MatrixData matrixData) : base() + { + var value = matrixData.ToByteArray(); + UnsafeNativeMethods.mp__MakeMatrixPacket__PKc_i(value, value.Length, out var ptr).Assert(); + this.ptr = ptr; + } + + public MatrixPacket(MatrixData matrixData, Timestamp timestamp) : base() + { + var value = matrixData.ToByteArray(); + UnsafeNativeMethods.mp__MakeMatrixPacket_At__PKc_i_Rt(value, value.Length, timestamp.mpPtr, out var ptr).Assert(); + GC.KeepAlive(timestamp); + this.ptr = ptr; + } + + public MatrixPacket At(Timestamp timestamp) + { + return At(timestamp); + } + + public override MatrixData Get() + { + UnsafeNativeMethods.mp_Packet__GetMatrix(mpPtr, out var serializedMatrixData).Assert(); + GC.KeepAlive(this); + + var matrixData = serializedMatrixData.Deserialize(MatrixData.Parser); + serializedMatrixData.Dispose(); + + return matrixData; + } + + public override StatusOr Consume() + { + throw new NotSupportedException(); + } + + public override Status ValidateAsType() + { + UnsafeNativeMethods.mp_Packet__ValidateAsMatrix(mpPtr, out var statusPtr).Assert(); + + GC.KeepAlive(this); + return new Status(statusPtr); + } + } +} diff --git a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Framework/Packet/MatrixPacket.cs.meta b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Framework/Packet/MatrixPacket.cs.meta new file mode 100644 index 000000000..2e04b5783 --- /dev/null +++ b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Framework/Packet/MatrixPacket.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ef898503888a0ee42af28aef1fbbe794 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/PInvoke/NativeMethods/External/Stdlib_Unsafe.cs b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/PInvoke/NativeMethods/External/Stdlib_Unsafe.cs index 5215dabd8..1965f17b4 100644 --- a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/PInvoke/NativeMethods/External/Stdlib_Unsafe.cs +++ b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/PInvoke/NativeMethods/External/Stdlib_Unsafe.cs @@ -14,6 +14,9 @@ internal static partial class UnsafeNativeMethods [DllImport(MediaPipeLibrary, ExactSpelling = true)] public static extern void delete_array__PKc(IntPtr str); + [DllImport(MediaPipeLibrary, ExactSpelling = true)] + public static extern void delete_array__Pf(IntPtr str); + #region String [DllImport(MediaPipeLibrary, ExactSpelling = true)] public static extern void std_string__delete(IntPtr str); diff --git a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/PInvoke/NativeMethods/Framework/Format/Matrix_Unsafe.cs b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/PInvoke/NativeMethods/Framework/Format/Matrix_Unsafe.cs new file mode 100644 index 000000000..bfc16aec5 --- /dev/null +++ b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/PInvoke/NativeMethods/Framework/Format/Matrix_Unsafe.cs @@ -0,0 +1,29 @@ +// Copyright (c) 2021 homuler +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. + +using System; +using System.Runtime.InteropServices; + +namespace Mediapipe +{ + internal static partial class UnsafeNativeMethods + { + #region Packet + [DllImport(MediaPipeLibrary, ExactSpelling = true)] + public static extern MpReturnCode mp__MakeMatrixPacket__PKc_i(byte[] serializedMatrixData, int size, out IntPtr packet_out); + + [DllImport(MediaPipeLibrary, ExactSpelling = true)] + public static extern MpReturnCode mp__MakeMatrixPacket_At__PKc_i_Rt(byte[] serializedMatrixData, int size, IntPtr timestamp, out IntPtr packet_out); + + [DllImport(MediaPipeLibrary, ExactSpelling = true)] + public static extern MpReturnCode mp_Packet__ValidateAsMatrix(IntPtr packet, out IntPtr status); + + [DllImport(MediaPipeLibrary, ExactSpelling = true)] + public static extern MpReturnCode mp_Packet__GetMatrix(IntPtr packet, out SerializedProto serializedProto); + + #endregion + } +} diff --git a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/PInvoke/NativeMethods/Framework/Format/Matrix_Unsafe.cs.meta b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/PInvoke/NativeMethods/Framework/Format/Matrix_Unsafe.cs.meta new file mode 100644 index 000000000..67688a598 --- /dev/null +++ b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/PInvoke/NativeMethods/Framework/Format/Matrix_Unsafe.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fc5345171757d2049a546634b03b8c5e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: 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 0e5d03392..a931f047f 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 @@ -87,12 +87,26 @@ internal static partial class UnsafeNativeMethods public static extern MpReturnCode mp__MakeFloatArrayPacket_At__Pf_i_Rt(float[] value, int size, IntPtr timestamp, out IntPtr packet); [DllImport(MediaPipeLibrary, ExactSpelling = true)] - public static extern MpReturnCode mp_Packet__GetFloatArray(IntPtr packet, out IntPtr value); + public static extern MpReturnCode mp_Packet__GetFloatArray_i(IntPtr packet, int size, out IntPtr value); [DllImport(MediaPipeLibrary, ExactSpelling = true)] public static extern MpReturnCode mp_Packet__ValidateAsFloatArray(IntPtr packet, out IntPtr status); #endregion + #region FloatVector + [DllImport(MediaPipeLibrary, ExactSpelling = true)] + public static extern MpReturnCode mp__MakeFloatVectorPacket__Pf_i(float[] value, int size, out IntPtr packet); + + [DllImport(MediaPipeLibrary, ExactSpelling = true)] + public static extern MpReturnCode mp__MakeFloatVectorPacket_At__Pf_i_Rt(float[] value, int size, IntPtr timestamp, out IntPtr packet); + + [DllImport(MediaPipeLibrary, ExactSpelling = true)] + public static extern MpReturnCode mp_Packet__GetFloatVector(IntPtr packet, out FloatVector value); + + [DllImport(MediaPipeLibrary, ExactSpelling = true)] + public static extern MpReturnCode mp_Packet__ValidateAsFloatVector(IntPtr packet, out IntPtr status); + #endregion + #region String [DllImport(MediaPipeLibrary, ExactSpelling = true)] public static extern MpReturnCode mp__MakeStringPacket__PKc(string value, out IntPtr packet); diff --git a/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/BoolPacketTest.cs b/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/BoolPacketTest.cs index f12d8cdd7..54e34bd66 100644 --- a/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/BoolPacketTest.cs +++ b/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/BoolPacketTest.cs @@ -118,13 +118,13 @@ public void Consume_ShouldThrowNotSupportedException() } #endregion - #region #DebugTypeName + #region #ValidateAsType [Test] - public void DebugTypeName_ShouldReturnBool_When_ValueIsSet() + public void ValidateAsType_ShouldReturnOk_When_ValueIsSet() { using (var packet = new BoolPacket(true)) { - Assert.AreEqual("bool", packet.DebugTypeName()); + Assert.True(packet.ValidateAsType().Ok()); } } #endregion diff --git a/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/FloatArrayPacketTest.cs b/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/FloatArrayPacketTest.cs index 59489c970..0ece68f43 100644 --- a/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/FloatArrayPacketTest.cs +++ b/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/FloatArrayPacketTest.cs @@ -122,18 +122,14 @@ public void Consume_ShouldThrowNotSupportedException() } #endregion - #region #DebugTypeName + #region #ValidateAsType [Test] - public void DebugTypeName_ShouldReturnFloat_When_ValueIsSet() + public void ValidateAsType_ShouldReturnOk_When_ValueIsSet() { float[] array = { 0.01f }; using (var packet = new FloatArrayPacket(array)) { -#if UNITY_EDITOR_WIN - Assert.AreEqual("float [0]", packet.DebugTypeName()); -#else - Assert.AreEqual("float []", packet.DebugTypeName()); -#endif + Assert.True(packet.ValidateAsType().Ok()); } } #endregion diff --git a/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/FloatPacketTest.cs b/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/FloatPacketTest.cs index e8c80132b..45d330036 100644 --- a/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/FloatPacketTest.cs +++ b/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/FloatPacketTest.cs @@ -106,13 +106,13 @@ public void Consume_ShouldThrowNotSupportedException() } #endregion - #region #DebugTypeName + #region #ValidateAsType [Test] - public void DebugTypeName_ShouldReturnFloat_When_ValueIsSet() + public void ValidateAsType_ShouldReturnOk_When_ValueIsSet() { using (var packet = new FloatPacket(0.01f)) { - Assert.AreEqual("float", packet.DebugTypeName()); + Assert.True(packet.ValidateAsType().Ok()); } } #endregion diff --git a/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/FloatVectorPacketTest.cs b/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/FloatVectorPacketTest.cs new file mode 100644 index 000000000..06d0da224 --- /dev/null +++ b/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/FloatVectorPacketTest.cs @@ -0,0 +1,176 @@ +// Copyright (c) 2021 homuler +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. + +using NUnit.Framework; +using System; +using System.Collections.Generic; + +namespace Mediapipe.Tests +{ + public class FloatVectorPacketTest + { + #region Constructor + [Test, SignalAbort] + public void Ctor_ShouldInstantiatePacket_When_CalledWithNoArguments() + { + using (var packet = new FloatVectorPacket()) + { +#pragma warning disable IDE0058 + Assert.AreEqual(Status.StatusCode.Internal, packet.ValidateAsType().Code()); + Assert.Throws(() => { packet.Get(); }); + Assert.AreEqual(Timestamp.Unset(), packet.Timestamp()); +#pragma warning restore IDE0058 + } + } + + [Test] + public void Ctor_ShouldInstantiatePacket_When_CalledWithEmptyArray() + { + float[] data = { }; + using (var packet = new FloatVectorPacket(data)) + { + Assert.True(packet.ValidateAsType().Ok()); + Assert.AreEqual(data, packet.Get()); + Assert.AreEqual(Timestamp.Unset(), packet.Timestamp()); + } + } + + [Test] + public void Ctor_ShouldInstantiatePacket_When_CalledWithArray() + { + float[] data = { 0.01f }; + using (var packet = new FloatVectorPacket(data)) + { + Assert.True(packet.ValidateAsType().Ok()); + Assert.AreEqual(data, packet.Get()); + Assert.AreEqual(Timestamp.Unset(), packet.Timestamp()); + } + } + + [Test] + public void Ctor_ShouldInstantiatePacket_When_CalledWithValueAndTimestamp() + { + float[] data = { 0.01f, 0.02f }; + using (var timestamp = new Timestamp(1)) + { + using (var packet = new FloatVectorPacket(data, timestamp)) + { + Assert.True(packet.ValidateAsType().Ok()); + Assert.AreEqual(data, packet.Get()); + Assert.AreEqual(timestamp, packet.Timestamp()); + } + } + } + + [Test] + public void Ctor_ShouldInstantiatePacket_When_CalledWithEmptyList() + { + var data = new List(); + using (var packet = new FloatVectorPacket(data)) + { + Assert.True(packet.ValidateAsType().Ok()); + Assert.AreEqual(data, packet.Get()); + Assert.AreEqual(Timestamp.Unset(), packet.Timestamp()); + } + } + + [Test] + public void Ctor_ShouldInstantiatePacket_When_CalledWithList() + { + var data = new List() { 0.01f }; + using (var packet = new FloatVectorPacket(data)) + { + Assert.True(packet.ValidateAsType().Ok()); + Assert.AreEqual(data, packet.Get()); + Assert.AreEqual(Timestamp.Unset(), packet.Timestamp()); + } + } + + [Test] + public void Ctor_ShouldInstantiatePacket_When_CalledWithListAndTimestamp() + { + var data = new List() { 0.01f, 0.02f }; + using (var timestamp = new Timestamp(1)) + { + using (var packet = new FloatVectorPacket(data, timestamp)) + { + Assert.True(packet.ValidateAsType().Ok()); + Assert.AreEqual(data, packet.Get()); + Assert.AreEqual(timestamp, packet.Timestamp()); + } + } + } + #endregion + + #region #isDisposed + [Test] + public void IsDisposed_ShouldReturnFalse_When_NotDisposedYet() + { + using (var packet = new FloatVectorPacket()) + { + Assert.False(packet.isDisposed); + } + } + + [Test] + public void IsDisposed_ShouldReturnTrue_When_AlreadyDisposed() + { + var packet = new FloatVectorPacket(); + packet.Dispose(); + + Assert.True(packet.isDisposed); + } + #endregion + + #region #At + [Test] + public void At_ShouldReturnNewPacketWithTimestamp() + { + using (var timestamp = new Timestamp(1)) + { + var data = new List() { 0.0f }; + var packet = new FloatVectorPacket(data).At(timestamp); + Assert.AreEqual(data, packet.Get()); + Assert.AreEqual(timestamp, packet.Timestamp()); + + using (var newTimestamp = new Timestamp(2)) + { + var newPacket = packet.At(newTimestamp); + Assert.AreEqual(data, newPacket.Get()); + Assert.AreEqual(newTimestamp, newPacket.Timestamp()); + } + + Assert.AreEqual(timestamp, packet.Timestamp()); + } + } + #endregion + + #region #Consume + [Test] + public void Consume_ShouldThrowNotSupportedException() + { + using (var packet = new FloatVectorPacket()) + { +#pragma warning disable IDE0058 + Assert.Throws(() => { packet.Consume(); }); +#pragma warning restore IDE0058 + } + } + #endregion + + #region #ValidateAsType + [Test] + public void ValidateAsType_ShouldReturnOk_When_ValueIsSet() + { + float[] array = { 0.01f }; + using (var packet = new FloatVectorPacket(array)) + { + Assert.True(packet.ValidateAsType().Ok()); + } + } + #endregion + } +} diff --git a/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/FloatVectorPacketTest.cs.meta b/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/FloatVectorPacketTest.cs.meta new file mode 100644 index 000000000..15a7a320d --- /dev/null +++ b/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/FloatVectorPacketTest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8a567519c65348c47ae2c5784431179e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/ImageFramePacketTest.cs b/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/ImageFramePacketTest.cs index eeaf5ddd2..359166daa 100644 --- a/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/ImageFramePacketTest.cs +++ b/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/ImageFramePacketTest.cs @@ -164,17 +164,13 @@ public void Consume_ShouldReturnImageFrame() } #endregion - #region #DebugTypeName + #region #ValidateAsType [Test] - public void DebugTypeName_ShouldReturnFloat_When_ValueIsSet() + public void ValidateAsType_ShouldReturnOk_When_ValueIsSet() { using (var packet = new ImageFramePacket(new ImageFrame())) { -#if UNITY_EDITOR_WIN - Assert.AreEqual("class mediapipe::ImageFrame", packet.DebugTypeName()); -#else - Assert.AreEqual("mediapipe::ImageFrame", packet.DebugTypeName()); -#endif + Assert.True(packet.ValidateAsType().Ok()); } } #endregion diff --git a/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/MatrixPacketTest.cs b/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/MatrixPacketTest.cs new file mode 100644 index 000000000..4d361e811 --- /dev/null +++ b/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/MatrixPacketTest.cs @@ -0,0 +1,111 @@ +// Copyright (c) 2021 homuler +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. + +using System.Collections.Generic; +using NUnit.Framework; +using System; + +namespace Mediapipe.Tests +{ + public class MatrixPacketTest + { + #region Constructor + [Test] + public void Ctor_ShouldInstantiatePacket_When_CalledWithValue() + { + var matrix = CreateMatrixInputData(); + using (var packet = new MatrixPacket(matrix)) + { + Assert.True(packet.ValidateAsType().Ok()); + Assert.AreEqual(matrix, packet.Get()); + Assert.AreEqual(Timestamp.Unset(), packet.Timestamp()); + } + } + #endregion + + #region #isDisposed + [Test] + public void IsDisposed_ShouldReturnFalse_When_NotDisposedYet() + { + using (var packet = new MatrixPacket()) + { + Assert.False(packet.isDisposed); + } + } + + [Test] + public void IsDisposed_ShouldReturnTrue_When_AlreadyDisposed() + { + var packet = new MatrixPacket(); + packet.Dispose(); + + Assert.True(packet.isDisposed); + } + #endregion + + #region #At + [Test] + public void At_ShouldReturnNewPacketWithTimestamp() + { + using (var timestamp = new Timestamp(1)) + { + var matrix = CreateMatrixInputData(); + var packet = new MatrixPacket(matrix).At(timestamp); + Assert.AreEqual(matrix, packet.Get()); + Assert.AreEqual(timestamp, packet.Timestamp()); + + using (var newTimestamp = new Timestamp(2)) + { + var newPacket = packet.At(newTimestamp); + Assert.AreEqual(matrix, newPacket.Get()); + Assert.AreEqual(newTimestamp, newPacket.Timestamp()); + } + + Assert.AreEqual(timestamp, packet.Timestamp()); + } + } + #endregion + + #region #Consume + [Test] + public void Consume_ShouldThrowNotSupportedException() + { + using (var packet = new MatrixPacket()) + { +#pragma warning disable IDE0058 + Assert.Throws(() => { packet.Consume(); }); +#pragma warning restore IDE0058 + } + } + #endregion + + #region #ValidateAsType + [Test] + public void ValidateAsType_ShouldReturnOk_When_ValueIsSet() + { + using (var packet = new MatrixPacket(CreateMatrixInputData())) + { + Assert.True(packet.ValidateAsType().Ok()); + } + } + #endregion + + private static MatrixData CreateMatrixInputData() + { + var matrix = new MatrixData(); + matrix.PackedData.Add(0); + matrix.PackedData.Add(1); + matrix.PackedData.Add(2); + matrix.PackedData.Add(3); + matrix.PackedData.Add(4); + matrix.PackedData.Add(5); + + matrix.Rows = 2; + matrix.Cols = 3; + return matrix; + } + } +} diff --git a/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/MatrixPacketTest.cs.meta b/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/MatrixPacketTest.cs.meta new file mode 100644 index 000000000..b349e3721 --- /dev/null +++ b/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/MatrixPacketTest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a3a4963f37dcdcc43a8292c2493c19bc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/StringPacketTest.cs b/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/StringPacketTest.cs index 36d8db2c9..f5b3ccc7e 100644 --- a/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/StringPacketTest.cs +++ b/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/Packet/StringPacketTest.cs @@ -163,15 +163,13 @@ public void Consume_ShouldReturnStatusOrString_When_PacketIsNotEmpty() } #endregion - #region #DebugTypeName + #region #ValidateAsType [Test] - public void DebugTypeName_ShouldReturnString_When_ValueIsSet() + public void ValidateAsType_ShouldReturnOk_When_ValueIsSet() { using (var packet = new StringPacket("test")) { - var regex = new Regex("string"); - - Assert.True(regex.IsMatch(packet.DebugTypeName())); + Assert.True(packet.ValidateAsType().Ok()); } } #endregion diff --git a/mediapipe_api/BUILD b/mediapipe_api/BUILD index cc4ba455f..7f0f6741a 100644 --- a/mediapipe_api/BUILD +++ b/mediapipe_api/BUILD @@ -195,6 +195,7 @@ cc_library( "//mediapipe_api/framework/formats:detection", "//mediapipe_api/framework/formats:image_frame", "//mediapipe_api/framework/formats:landmark", + "//mediapipe_api/framework/formats:matrix_data", "//mediapipe_api/framework/formats:rect", "//mediapipe_api/framework/port:logging", "//mediapipe_api/graphs/object_detection_3d/calculators:model_matrix", diff --git a/mediapipe_api/external/protobuf.h b/mediapipe_api/external/protobuf.h index 1f0f9daf0..248b5002c 100644 --- a/mediapipe_api/external/protobuf.h +++ b/mediapipe_api/external/protobuf.h @@ -46,6 +46,14 @@ inline void SerializeProtoVector(const std::vector& proto_vec, mp_api::Struct serialized_proto_vector->size = static_cast(vec_size); } +template +inline T ParseFromStringAsProto(const char* serialized_data, int size) { + T proto; + CHECK(proto.ParseFromString(std::string(serialized_data, size))); + + return proto; +} + template inline bool ConvertFromTextFormat(const char* str, mp_api::SerializedProto* output) { T proto; diff --git a/mediapipe_api/external/stdlib.cc b/mediapipe_api/external/stdlib.cc index 0f15e7b74..04dd686d9 100644 --- a/mediapipe_api/external/stdlib.cc +++ b/mediapipe_api/external/stdlib.cc @@ -8,6 +8,8 @@ void delete_array__PKc(const char* str) { delete[] str; } +void delete_array__Pf(float* f) { delete[] f; } + void std_string__delete(std::string* str) { delete str; } MpReturnCode std_string__PKc_i(const char* src, int size, std::string** str_out) { diff --git a/mediapipe_api/external/stdlib.h b/mediapipe_api/external/stdlib.h index c9edbfbc4..f5932fe8c 100644 --- a/mediapipe_api/external/stdlib.h +++ b/mediapipe_api/external/stdlib.h @@ -15,6 +15,7 @@ extern "C" { MP_CAPI(void) delete_array__PKc(const char* str); +MP_CAPI(void) delete_array__Pf(float* f); // string API MP_CAPI(void) std_string__delete(std::string* str); diff --git a/mediapipe_api/framework/calculator_graph.cc b/mediapipe_api/framework/calculator_graph.cc index fcc46698c..5341211aa 100644 --- a/mediapipe_api/framework/calculator_graph.cc +++ b/mediapipe_api/framework/calculator_graph.cc @@ -8,13 +8,6 @@ #include -inline mediapipe::CalculatorGraphConfig ParseFromStringAsCalculatorGraphConfig(const char* serialized_config, int size) { - mediapipe::CalculatorGraphConfig config; - CHECK(config.ParseFromString(std::string(serialized_config, size))); - - return config; -} - MpReturnCode mp_CalculatorGraph__(mediapipe::CalculatorGraph** graph_out) { TRY *graph_out = new mediapipe::CalculatorGraph(); @@ -26,7 +19,7 @@ void mp_CalculatorGraph__delete(mediapipe::CalculatorGraph* graph) { delete grap MpReturnCode mp_CalculatorGraph__PKc_i(const char* serialized_config, int size, mediapipe::CalculatorGraph** graph_out) { TRY_ALL - auto config = ParseFromStringAsCalculatorGraphConfig(serialized_config, size); + auto config = ParseFromStringAsProto(serialized_config, size); *graph_out = new mediapipe::CalculatorGraph(config); RETURN_CODE(MpReturnCode::Success); CATCH_ALL @@ -34,7 +27,7 @@ MpReturnCode mp_CalculatorGraph__PKc_i(const char* serialized_config, int size, MpReturnCode mp_CalculatorGraph__Initialize__PKc_i(mediapipe::CalculatorGraph* graph, const char* serialized_config, int size, absl::Status** status_out) { TRY_ALL - auto config = ParseFromStringAsCalculatorGraphConfig(serialized_config, size); + auto config = ParseFromStringAsProto(serialized_config, size); *status_out = new absl::Status{graph->Initialize(config)}; RETURN_CODE(MpReturnCode::Success); CATCH_ALL @@ -43,7 +36,7 @@ MpReturnCode mp_CalculatorGraph__Initialize__PKc_i(mediapipe::CalculatorGraph* g MpReturnCode mp_CalculatorGraph__Initialize__PKc_i_Rsp(mediapipe::CalculatorGraph* graph, const char* serialized_config, int size, SidePackets* side_packets, absl::Status** status_out) { TRY_ALL - auto config = ParseFromStringAsCalculatorGraphConfig(serialized_config, size); + auto config = ParseFromStringAsProto(serialized_config, size); *status_out = new absl::Status{graph->Initialize(config, *side_packets)}; RETURN_CODE(MpReturnCode::Success); CATCH_ALL diff --git a/mediapipe_api/framework/formats/BUILD b/mediapipe_api/framework/formats/BUILD index 6bd9f8966..e3b28a09f 100644 --- a/mediapipe_api/framework/formats/BUILD +++ b/mediapipe_api/framework/formats/BUILD @@ -64,6 +64,21 @@ cc_library( alwayslink = True, ) +cc_library( + name = "matrix_data", + srcs = ["matrix_data.cc"], + hdrs = ["matrix_data.h"], + deps = [ + "//mediapipe_api:common", + "//mediapipe_api/external/absl:status", + "//mediapipe_api/external/absl:statusor", + "//mediapipe_api/framework:packet", + "@com_google_mediapipe//mediapipe/framework/formats:matrix", + "@com_google_mediapipe//mediapipe/framework/formats:matrix_data_cc_proto", + ], + alwayslink = True, +) + cc_library( name = "rect", srcs = ["rect.cc"], diff --git a/mediapipe_api/framework/formats/matrix_data.cc b/mediapipe_api/framework/formats/matrix_data.cc new file mode 100644 index 000000000..b3e7b7578 --- /dev/null +++ b/mediapipe_api/framework/formats/matrix_data.cc @@ -0,0 +1,50 @@ +// Copyright (c) 2021 homuler +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. + +#include "mediapipe_api/framework/formats/matrix_data.h" + +MpReturnCode mp__MakeMatrixPacket__PKc_i(const char* serialized_matrix_data, int size, mediapipe::Packet** packet_out) { + TRY + auto matrix_data = ParseFromStringAsProto(serialized_matrix_data, size); + + mediapipe::Matrix matrix; + mediapipe::MatrixFromMatrixDataProto(matrix_data, &matrix); + + *packet_out = new mediapipe::Packet{mediapipe::MakePacket(matrix)}; + RETURN_CODE(MpReturnCode::Success); + CATCH_EXCEPTION +} + +MpReturnCode mp__MakeMatrixPacket_At__PKc_i_Rt(const char* serialized_matrix_data, int size, mediapipe::Timestamp* timestamp, mediapipe::Packet** packet_out) { + TRY + auto matrix_data = ParseFromStringAsProto(serialized_matrix_data, size); + + mediapipe::Matrix matrix; + mediapipe::MatrixFromMatrixDataProto(matrix_data, &matrix); + + *packet_out = new mediapipe::Packet{mediapipe::MakePacket(matrix).At(*timestamp)}; + RETURN_CODE(MpReturnCode::Success); + CATCH_EXCEPTION +} + +MP_CAPI(MpReturnCode) mp_Packet__GetMatrix(mediapipe::Packet* packet, mp_api::SerializedProto* value_out) { + TRY + mediapipe::MatrixData matrix_data; + auto matrix = packet->Get(); + mediapipe::MatrixDataProtoFromMatrix(matrix, &matrix_data); + + SerializeProto(matrix_data, value_out); + + RETURN_CODE(MpReturnCode::Success); + CATCH_EXCEPTION +} + +MP_CAPI(MpReturnCode) mp_Packet__ValidateAsMatrix(mediapipe::Packet* packet, absl::Status** status_out) { + TRY + *status_out = new absl::Status{packet->ValidateAsType()}; + RETURN_CODE(MpReturnCode::Success); + CATCH_EXCEPTION +} diff --git a/mediapipe_api/framework/formats/matrix_data.h b/mediapipe_api/framework/formats/matrix_data.h new file mode 100644 index 000000000..6580093f2 --- /dev/null +++ b/mediapipe_api/framework/formats/matrix_data.h @@ -0,0 +1,25 @@ +// Copyright (c) 2021 homuler +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. + +#ifndef MEDIAPIPE_API_FRAMEWORK_FORMATS_MATRIX_DATA_H_ +#define MEDIAPIPE_API_FRAMEWORK_FORMATS_MATRIX_DATA_H_ + +#include "mediapipe/framework/formats/matrix.h" +#include "mediapipe_api/common.h" +#include "mediapipe_api/external/protobuf.h" +#include "mediapipe_api/framework/packet.h" + +extern "C" { + +MP_CAPI(MpReturnCode) mp__MakeMatrixPacket__PKc_i(const char* matrix_data_serialized, int size, mediapipe::Packet** packet_out); +MP_CAPI(MpReturnCode) mp__MakeMatrixPacket_At__PKc_i_Rt(const char* matrix_data_serialized, int size, mediapipe::Timestamp* timestamp, + mediapipe::Packet** packet_out); +MP_CAPI(MpReturnCode) mp_Packet__GetMatrix(mediapipe::Packet* packet, mp_api::SerializedProto* value_out); +MP_CAPI(MpReturnCode) mp_Packet__ValidateAsMatrix(mediapipe::Packet* packet, absl::Status** status_out); + +} // extern "C" + +#endif // MEDIAPIPE_API_FRAMEWORK_FORMATS_MATRIX_DATA_H_ diff --git a/mediapipe_api/framework/packet.cc b/mediapipe_api/framework/packet.cc index cd500ad60..b435799e8 100644 --- a/mediapipe_api/framework/packet.cc +++ b/mediapipe_api/framework/packet.cc @@ -169,9 +169,12 @@ MpReturnCode mp__MakeFloatArrayPacket_At__Pf_i_Rt(float* value, int size, mediap CATCH_EXCEPTION } -MpReturnCode mp_Packet__GetFloatArray(mediapipe::Packet* packet, const float** value_out) { +MpReturnCode mp_Packet__GetFloatArray_i(mediapipe::Packet* packet, int size, const float** value_out) { TRY_ALL - *value_out = packet->Get(); + auto src = packet->Get(); + auto dst = new float[size]; + std::memcpy(dst, src, size * sizeof(float)); + *value_out = dst; RETURN_CODE(MpReturnCode::Success); CATCH_ALL } @@ -183,6 +186,24 @@ MpReturnCode mp_Packet__ValidateAsFloatArray(mediapipe::Packet* packet, absl::St CATCH_EXCEPTION } +// FloatVectorPacket +MpReturnCode mp__MakeFloatVectorPacket__Pf_i(float* value, int size, mediapipe::Packet** packet_out) { return mp__MakeVectorPacket(value, size, packet_out); } + +MpReturnCode mp__MakeFloatVectorPacket_At__Pf_i_Rt(float* value, int size, mediapipe::Timestamp* timestamp, mediapipe::Packet** packet_out) { + return mp__MakeVectorPacket_At(value, size, timestamp, packet_out); +} + +MpReturnCode mp_Packet__GetFloatVector(mediapipe::Packet* packet, mp_api::StructArray* value_out) { + return mp_Packet__GetStructVector(packet, value_out); +} + +MpReturnCode mp_Packet__ValidateAsFloatVector(mediapipe::Packet* packet, absl::Status** status_out) { + TRY + *status_out = new absl::Status{packet->ValidateAsType>()}; + RETURN_CODE(MpReturnCode::Success); + CATCH_EXCEPTION +} + // StringPacket MpReturnCode mp__MakeStringPacket__PKc(const char* str, mediapipe::Packet** packet_out) { TRY diff --git a/mediapipe_api/framework/packet.h b/mediapipe_api/framework/packet.h index ba9009eb0..b74fa0397 100644 --- a/mediapipe_api/framework/packet.h +++ b/mediapipe_api/framework/packet.h @@ -44,30 +44,36 @@ MP_CAPI(MpReturnCode) mp_Packet__DebugString(mediapipe::Packet* packet, const ch MP_CAPI(MpReturnCode) mp_Packet__RegisteredTypeName(mediapipe::Packet* packet, const char** str_out); MP_CAPI(MpReturnCode) mp_Packet__DebugTypeName(mediapipe::Packet* packet, const char** str_out); -// Boolean +// bool MP_CAPI(MpReturnCode) mp__MakeBoolPacket__b(bool value, mediapipe::Packet** packet_out); MP_CAPI(MpReturnCode) mp__MakeBoolPacket_At__b_Rt(bool value, mediapipe::Timestamp* timestamp, mediapipe::Packet** packet_out); 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); -// Float +// 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); MP_CAPI(MpReturnCode) mp_Packet__GetFloat(mediapipe::Packet* packet, float* value_out); MP_CAPI(MpReturnCode) mp_Packet__ValidateAsFloat(mediapipe::Packet* packet, absl::Status** status_out); -// Int +// int MP_CAPI(MpReturnCode) mp__MakeIntPacket__i(int value, mediapipe::Packet** packet_out); MP_CAPI(MpReturnCode) mp__MakeIntPacket_At__i_Rt(int value, mediapipe::Timestamp* timestamp, mediapipe::Packet** packet_out); MP_CAPI(MpReturnCode) mp_Packet__GetInt(mediapipe::Packet* packet, int* value_out); MP_CAPI(MpReturnCode) mp_Packet__ValidateAsInt(mediapipe::Packet* packet, absl::Status** status_out); -// Float Array +// float[] MP_CAPI(MpReturnCode) mp__MakeFloatArrayPacket__Pf_i(float* value, int size, mediapipe::Packet** packet_out); MP_CAPI(MpReturnCode) mp__MakeFloatArrayPacket_At__Pf_i_Rt(float* value, int size, mediapipe::Timestamp* timestamp, mediapipe::Packet** packet_out); -MP_CAPI(MpReturnCode) mp_Packet__GetFloatArray(mediapipe::Packet* packet, const float** value_out); +MP_CAPI(MpReturnCode) mp_Packet__GetFloatArray_i(mediapipe::Packet* packet, int size, const float** value_out); MP_CAPI(MpReturnCode) mp_Packet__ValidateAsFloatArray(mediapipe::Packet* packet, absl::Status** status_out); +// std::vector +MP_CAPI(MpReturnCode) mp__MakeFloatVectorPacket__Pf_i(float* value, int size, mediapipe::Packet** packet_out); +MP_CAPI(MpReturnCode) mp__MakeFloatVectorPacket_At__Pf_i_Rt(float* value, int size, mediapipe::Timestamp* timestamp, mediapipe::Packet** packet_out); +MP_CAPI(MpReturnCode) mp_Packet__GetFloatVector(mediapipe::Packet* packet, mp_api::StructArray* value_out); +MP_CAPI(MpReturnCode) mp_Packet__ValidateAsFloatVector(mediapipe::Packet* packet, absl::Status** status_out); + // String MP_CAPI(MpReturnCode) mp__MakeStringPacket__PKc(const char* str, mediapipe::Packet** packet_out); MP_CAPI(MpReturnCode) mp__MakeStringPacket_At__PKc_Rt(const char* str, mediapipe::Timestamp* timestamp, mediapipe::Packet** packet_out); @@ -118,6 +124,26 @@ inline MpReturnCode mp_Packet__Get(mediapipe::Packet* packet, const T** value_ou CATCH_ALL } +// std::vector + +template +inline MpReturnCode mp__MakeVectorPacket(const T* array, int size, mediapipe::Packet** packet_out) { + TRY + std::vector vector(array, array + size); + *packet_out = new mediapipe::Packet{mediapipe::MakePacket>(vector)}; + RETURN_CODE(MpReturnCode::Success); + CATCH_EXCEPTION +} + +template +inline MpReturnCode mp__MakeVectorPacket_At(const T* array, int size, mediapipe::Timestamp* timestamp, mediapipe::Packet** packet_out) { + TRY + std::vector vector(array, array + size); + *packet_out = new mediapipe::Packet{mediapipe::MakePacket>(vector).At(*timestamp)}; + RETURN_CODE(MpReturnCode::Success); + CATCH_EXCEPTION +} + template inline MpReturnCode mp_Packet__GetStructVector(mediapipe::Packet* packet, mp_api::StructArray* value_out) { TRY_ALL @@ -134,6 +160,8 @@ inline MpReturnCode mp_Packet__GetStructVector(mediapipe::Packet* packet, mp_api CATCH_ALL } +// SerializedProto + template inline MpReturnCode mp_Packet__GetSerializedProto(mediapipe::Packet* packet, mp_api::SerializedProto* value_out) { TRY_ALL diff --git a/mediapipe_api/framework/validated_graph_config.cc b/mediapipe_api/framework/validated_graph_config.cc index 670d7776e..46edd120f 100644 --- a/mediapipe_api/framework/validated_graph_config.cc +++ b/mediapipe_api/framework/validated_graph_config.cc @@ -12,9 +12,7 @@ void mp_ValidatedGraphConfig__delete(mediapipe::ValidatedGraphConfig* config) { MpReturnCode mp_ValidatedGraphConfig__Initialize__Rcgc(mediapipe::ValidatedGraphConfig* config, const char* serialized_config, int size, absl::Status** status_out) { TRY - mediapipe::CalculatorGraphConfig graph_config; - CHECK(graph_config.ParseFromString(std::string(serialized_config, size))); - + auto graph_config = ParseFromStringAsProto(serialized_config, size); auto status = config->Initialize(graph_config); *status_out = new absl::Status(std::move(status)); RETURN_CODE(MpReturnCode::Success);