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 cee57ac9a..aea5b6016 100644 --- a/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Framework/Packet.cs +++ b/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Framework/Packet.cs @@ -298,6 +298,52 @@ public static Packet CreateProtoAt(T value, long timestampMicrosec) where T : } } + /// + /// Create a string Packet. + /// + public static Packet CreateString(string value) + { + UnsafeNativeMethods.mp__MakeStringPacket__PKc(value ?? "", out var ptr).Assert(); + + return new Packet(ptr, true); + } + + /// + /// Create a string Packet. + /// + public static Packet CreateString(byte[] value) + { + UnsafeNativeMethods.mp__MakeStringPacket__PKc_i(value, value?.Length ?? 0, out var ptr).Assert(); + + return new Packet(ptr, true); + } + + /// + /// Create a string Packet. + /// + /// + /// The timestamp of the packet. + /// + public static Packet CreateStringAt(string value, long timestampMicrosec) + { + UnsafeNativeMethods.mp__MakeStringPacket_At__PKc_ll(value ?? "", timestampMicrosec, out var ptr).Assert(); + + return new Packet(ptr, true); + } + + /// + /// Create a string Packet. + /// + /// + /// The timestamp of the packet. + /// + public static Packet CreateStringAt(byte[] value, long timestampMicrosec) + { + UnsafeNativeMethods.mp__MakeStringPacket_At__PKc_i_ll(value, value?.Length ?? 0, timestampMicrosec, out var ptr).Assert(); + + return new Packet(ptr, true); + } + /// /// Get the content of the as a boolean. /// @@ -347,6 +393,56 @@ public void GetBoolList(List value) structArray.Dispose(); } + /// + /// Get the content of the as . + /// + /// + /// On some platforms (e.g. Windows), it will abort the process when should be thrown. + /// + /// + /// If the doesn't contain data. + /// + public byte[] GetBytes() + { + UnsafeNativeMethods.mp_Packet__GetByteString(mpPtr, out var strPtr, out var size).Assert(); + GC.KeepAlive(this); + + var bytes = new byte[size]; + Marshal.Copy(strPtr, bytes, 0, size); + UnsafeNativeMethods.delete_array__PKc(strPtr); + + return bytes; + } + + /// + /// Get the content of the as . + /// + /// + /// On some platforms (e.g. Windows), it will abort the process when should be thrown. + /// + /// + /// The to be filled with the content of the . + /// If the length of is not enough to store the content of the , + /// the rest of the content will be discarded. + /// + /// + /// The number of written elements in . + /// + /// + /// If the doesn't contain data. + /// + public int GetBytes(byte[] value) + { + UnsafeNativeMethods.mp_Packet__GetByteString(mpPtr, out var strPtr, out var size).Assert(); + GC.KeepAlive(this); + + var length = Math.Min(size, value.Length); + Marshal.Copy(strPtr, value, 0, length); + UnsafeNativeMethods.delete_array__PKc(strPtr); + + return length; + } + /// /// Get the content of the as a double. /// @@ -646,6 +742,23 @@ public void GetDetectionList(List outs) outs.RemoveRange(size, outs.Count - size); } + /// + /// Get the content of the as a string. + /// + /// + /// On some platforms (e.g. Windows), it will abort the process when should be thrown. + /// + /// + /// If the doesn't contain data. + /// + public string GetString() + { + UnsafeNativeMethods.mp_Packet__GetString(mpPtr, out var ptr).Assert(); + + GC.KeepAlive(this); + return MarshalStringFromNative(ptr); + } + /// /// Validate if the content of the is a boolean. /// @@ -785,5 +898,19 @@ public void ValidateAsProtoMessageLite() GC.KeepAlive(this); AssertStatusOk(statusPtr); } + + /// + /// Validate if the content of the is a string. + /// + /// + /// If the doesn't contain string. + /// + public void ValidateAsString() + { + UnsafeNativeMethods.mp_Packet__ValidateAsString(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 7640756cd..8996fb93a 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 @@ -154,12 +154,18 @@ internal static partial class UnsafeNativeMethods [DllImport(MediaPipeLibrary, ExactSpelling = true)] public static extern MpReturnCode mp__MakeStringPacket_At__PKc_Rt(string value, IntPtr timestamp, out IntPtr packet); + [DllImport(MediaPipeLibrary, ExactSpelling = true)] + public static extern MpReturnCode mp__MakeStringPacket_At__PKc_ll(string value, long timestampMicrosec, out IntPtr packet); + [DllImport(MediaPipeLibrary, ExactSpelling = true)] public static extern MpReturnCode mp__MakeStringPacket__PKc_i(byte[] bytes, int size, out IntPtr packet); [DllImport(MediaPipeLibrary, ExactSpelling = true)] public static extern MpReturnCode mp__MakeStringPacket_At__PKc_i_Rt(byte[] bytes, int size, IntPtr timestamp, out IntPtr packet); + [DllImport(MediaPipeLibrary, ExactSpelling = true)] + public static extern MpReturnCode mp__MakeStringPacket_At__PKc_i_ll(byte[] bytes, int size, long timestampMicrosec, out IntPtr packet); + [DllImport(MediaPipeLibrary, ExactSpelling = true)] public static extern MpReturnCode mp_Packet__GetString(IntPtr packet, out IntPtr value); 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 0cdd3500b..dff0b671e 100644 --- a/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/PacketTest.cs +++ b/Packages/com.github.homuler.mediapipe/Tests/EditMode/Framework/PacketTest.cs @@ -361,6 +361,151 @@ public void CreateProtoAt_ShouldReturnNewProtoPacket() } #endregion + + #region String + [Test] + public void CreateString_ShouldReturnNewStringPacket_When_ValueIsNullString() + { + using var packet = Packet.CreateString((string)null); + + Assert.DoesNotThrow(packet.ValidateAsString); + Assert.IsNull(packet.GetString()); + + using var unsetTimestamp = Timestamp.Unset(); + Assert.AreEqual(unsetTimestamp.Microseconds(), packet.TimestampMicroseconds()); + } + + [Test] + public void CreateString_ShouldReturnNewStringPacket_When_ValueIsEmptyString() + { + using var packet = Packet.CreateString(""); + + Assert.DoesNotThrow(packet.ValidateAsString); + Assert.IsNull(packet.GetString()); + + using var unsetTimestamp = Timestamp.Unset(); + Assert.AreEqual(unsetTimestamp.Microseconds(), packet.TimestampMicroseconds()); + } + + [TestCase("hello")] + public void CreateString_ShouldReturnNewStringPacket_When_StringIsGiven(string value) + { + using var packet = Packet.CreateString(value); + + Assert.DoesNotThrow(packet.ValidateAsString); + Assert.AreEqual(value, packet.GetString()); + + using var unsetTimestamp = Timestamp.Unset(); + Assert.AreEqual(unsetTimestamp.Microseconds(), packet.TimestampMicroseconds()); + } + + [Test] + public void CreateString_ShouldReturnNewStringPacket_When_ValueIsNullArray() + { + using var packet = Packet.CreateString((byte[])null); + + Assert.DoesNotThrow(packet.ValidateAsString); + Assert.IsEmpty(packet.GetBytes()); + + using var unsetTimestamp = Timestamp.Unset(); + Assert.AreEqual(unsetTimestamp.Microseconds(), packet.TimestampMicroseconds()); + } + + [Test] + public void CreateString_ShouldReturnNewStringPacket_When_ValueIsEmptyArray() + { + var value = new byte[] { }; + using var packet = Packet.CreateString(value); + + Assert.DoesNotThrow(packet.ValidateAsString); + Assert.IsEmpty(packet.GetBytes()); + + using var unsetTimestamp = Timestamp.Unset(); + Assert.AreEqual(unsetTimestamp.Microseconds(), packet.TimestampMicroseconds()); + } + + [Test] + public void CreateString_ShouldReturnNewStringPacket_When_ByteArrayIsGiven() + { + var value = new byte[] { 1, 2, 3 }; + using var packet = Packet.CreateString(value); + + Assert.DoesNotThrow(packet.ValidateAsString); + Assert.AreEqual(value, packet.GetBytes()); + + using var unsetTimestamp = Timestamp.Unset(); + Assert.AreEqual(unsetTimestamp.Microseconds(), packet.TimestampMicroseconds()); + } + + [Test] + public void CreateStringAt_ShouldReturnNewStringPacket_When_ValueIsNullString() + { + var timestamp = 1; + using var packet = Packet.CreateStringAt((string)null, timestamp); + + Assert.DoesNotThrow(packet.ValidateAsString); + Assert.IsNull(packet.GetString()); + Assert.AreEqual(timestamp, packet.TimestampMicroseconds()); + } + + [Test] + public void CreateStringAt_ShouldReturnNewStringPacket_When_ValueIsEmptyString() + { + var timestamp = 1; + using var packet = Packet.CreateStringAt("", timestamp); + + Assert.DoesNotThrow(packet.ValidateAsString); + Assert.IsNull(packet.GetString()); + Assert.AreEqual(timestamp, packet.TimestampMicroseconds()); + } + + [TestCase("hello")] + public void CreateStringAt_ShouldReturnNewStringPacket_When_StringIsGiven(string value) + { + var timestamp = 1; + using var packet = Packet.CreateStringAt(value, timestamp); + + Assert.DoesNotThrow(packet.ValidateAsString); + Assert.AreEqual(value, packet.GetString()); + Assert.AreEqual(timestamp, packet.TimestampMicroseconds()); + } + + [Test] + public void CreateStringAt_ShouldReturnNewStringPacket_When_ValueIsNullArray() + { + var timestamp = 1; + using var packet = Packet.CreateStringAt((byte[])null, timestamp); + + Assert.DoesNotThrow(packet.ValidateAsString); + Assert.IsEmpty(packet.GetBytes()); + Assert.AreEqual(timestamp, packet.TimestampMicroseconds()); + } + + [Test] + public void CreateStringAt_ShouldReturnNewStringPacket_When_ValueIsEmptyArray() + { + var timestamp = 1; + var value = new byte[] { }; + using var packet = Packet.CreateStringAt(value, timestamp); + + Assert.DoesNotThrow(packet.ValidateAsString); + Assert.IsEmpty(packet.GetBytes()); + Assert.AreEqual(timestamp, packet.TimestampMicroseconds()); + } + + [Test] + public void CreateStringAt_ShouldReturnNewStringPacket_When_ByteArrayIsGiven() + { + var timestamp = 1; + var value = new byte[] { 1, 2, 3 }; + using var packet = Packet.CreateStringAt(value, timestamp); + + Assert.DoesNotThrow(packet.ValidateAsString); + Assert.AreEqual(value, packet.GetBytes()); + Assert.AreEqual(timestamp, packet.TimestampMicroseconds()); + } + #endregion + #region #Validate [Test] public void ValidateAsBool_ShouldThrow_When_ValueIsNotSet() diff --git a/mediapipe_api/framework/packet.cc b/mediapipe_api/framework/packet.cc index b88455e52..f8638274c 100644 --- a/mediapipe_api/framework/packet.cc +++ b/mediapipe_api/framework/packet.cc @@ -299,6 +299,13 @@ MpReturnCode mp__MakeStringPacket_At__PKc_Rt(const char* str, mediapipe::Timesta CATCH_EXCEPTION } +MpReturnCode mp__MakeStringPacket_At__PKc_ll(const char* str, int64 timestampMicrosec, mediapipe::Packet** packet_out) { + TRY + *packet_out = new mediapipe::Packet{mediapipe::MakePacket(std::string(str)).At(mediapipe::Timestamp(timestampMicrosec))}; + RETURN_CODE(MpReturnCode::Success); + CATCH_EXCEPTION +} + MpReturnCode mp__MakeStringPacket__PKc_i(const char* str, int size, mediapipe::Packet** packet_out) { TRY *packet_out = new mediapipe::Packet{mediapipe::MakePacket(std::string(str, size))}; @@ -313,6 +320,13 @@ MpReturnCode mp__MakeStringPacket_At__PKc_i_Rt(const char* str, int size, mediap CATCH_EXCEPTION } +MpReturnCode mp__MakeStringPacket_At__PKc_i_ll(const char* str, int size, int64 timestampMicrosec, mediapipe::Packet** packet_out) { + TRY + *packet_out = new mediapipe::Packet{mediapipe::MakePacket(std::string(str, size)).At(mediapipe::Timestamp(timestampMicrosec))}; + RETURN_CODE(MpReturnCode::Success); + CATCH_EXCEPTION +} + MpReturnCode mp_Packet__GetString(mediapipe::Packet* packet, const char** value_out) { TRY_ALL *value_out = strcpy_to_heap(packet->Get()); diff --git a/mediapipe_api/framework/packet.h b/mediapipe_api/framework/packet.h index 0b111a96f..1116f10a2 100644 --- a/mediapipe_api/framework/packet.h +++ b/mediapipe_api/framework/packet.h @@ -94,8 +94,10 @@ MP_CAPI(MpReturnCode) mp_Packet__ValidateAsInt(mediapipe::Packet* packet, absl:: // 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); +MP_CAPI(MpReturnCode) mp__MakeStringPacket_At__PKc_ll(const char* str, int64 timestampMicrosec, mediapipe::Packet** packet_out); MP_CAPI(MpReturnCode) mp__MakeStringPacket__PKc_i(const char* str, int size, mediapipe::Packet** packet_out); MP_CAPI(MpReturnCode) mp__MakeStringPacket_At__PKc_i_Rt(const char* str, int size, mediapipe::Timestamp* timestamp, mediapipe::Packet** packet_out); +MP_CAPI(MpReturnCode) mp__MakeStringPacket_At__PKc_i_ll(const char* str, int size, int64 timestampMicrosec, mediapipe::Packet** packet_out); MP_CAPI(MpReturnCode) mp_Packet__GetString(mediapipe::Packet* packet, const char** value_out); MP_CAPI(MpReturnCode) mp_Packet__GetByteString(mediapipe::Packet* packet, const char** value_out, int* size_out); MP_CAPI(MpReturnCode) mp_Packet__ConsumeString(mediapipe::Packet* packet, absl::Status** status_out, const char** value_out);