diff --git a/HyperTizen/Capturer.cs b/HyperTizen/Capturer.cs
deleted file mode 100644
index 588ed70..0000000
--- a/HyperTizen/Capturer.cs
+++ /dev/null
@@ -1,275 +0,0 @@
-using System;
-using System.IO;
-using System.Runtime.InteropServices;
-using System.Threading;
-using SkiaSharp;
-using Tizen.Applications.Notifications;
-using Tizen.System;
-
-namespace HyperTizen
-{
- public static class Capturer
- {
- private static Condition _condition;
-
- private static bool IsTizen7OrHigher
- {
- get
- {
- string version;
- Information.TryGetValue("http://tizen.org/feature/platform.version", out version);
- if (int.Parse(version.Split('.')[0]) >= 7)
- {
- return true;
- } else
- {
- return false;
- }
- }
- }
-
- private static CapturePoint[] _capturedPoints = new CapturePoint[] {
- new CapturePoint(0.21, 0.05),
- new CapturePoint(0.45, 0.05),
- new CapturePoint(0.7, 0.05),
- new CapturePoint(0.93, 0.07),
- new CapturePoint(0.95, 0.275),
- new CapturePoint(0.95, 0.5),
- new CapturePoint(0.95, 0.8),
- new CapturePoint(0.79, 0.95),
- new CapturePoint(0.65, 0.95),
- new CapturePoint(0.35, 0.95),
- new CapturePoint(0.15, 0.95),
- new CapturePoint(0.05, 0.725),
- new CapturePoint(0.05, 0.4),
- new CapturePoint(0.05, 0.2),
- new CapturePoint(0.35, 0.5),
- new CapturePoint(0.65, 0.5)
- };
-
- [DllImport("/usr/lib/libvideoenhance.so", CallingConvention = CallingConvention.Cdecl, EntryPoint = "cs_ve_get_rgb_measure_condition")]
- private static extern int MeasureCondition(out Condition unknown);
-
- [DllImport("/usr/lib/libvideoenhance.so", CallingConvention = CallingConvention.Cdecl, EntryPoint = "cs_ve_set_rgb_measure_position")]
- private static extern int MeasurePosition(int i, int x, int y);
-
- [DllImport("/usr/lib/libvideoenhance.so", CallingConvention = CallingConvention.Cdecl, EntryPoint = "cs_ve_get_rgb_measure_pixel")]
- private static extern int MeasurePixel(int i, out Color color);
-
- [DllImport("/usr/lib/libvideoenhance.so", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ve_get_rgb_measure_condition")]
- private static extern int MeasureCondition7(out Condition unknown);
-
- [DllImport("/usr/lib/libvideoenhance.so", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ve_set_rgb_measure_position")]
- private static extern int MeasurePosition7(int i, int x, int y);
-
- [DllImport("/usr/lib/libvideoenhance.so", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ve_get_rgb_measure_pixel")]
- private static extern int MeasurePixel7(int i, out Color color);
-
- public static bool GetCondition()
- {
- int res = -1;
- try
- {
- if (!IsTizen7OrHigher)
- {
- res = MeasureCondition(out _condition);
- } else
- {
- res = MeasureCondition7(out _condition);
- }
- } catch
- {
- Notification notification = new Notification
- {
- Title = "HyperTizen",
- Content = "Your TV does not support the required functions for HyperTizen.",
- Count = 1
- };
-
- NotificationManager.Post(notification);
- }
- if (res < 0)
- {
- return false;
- } else
- {
- return true;
- }
- }
-
- public static void SetCapturePoints(CapturePoint[] capturePoints)
- {
- _capturedPoints = capturePoints;
- }
-
- public static Color[] GetColors()
- {
- Color[] colorData = new Color[_capturedPoints.Length];
- int[] updatedIndexes = new int[_condition.ScreenCapturePoints];
-
- int i = 0;
- while (i < _capturedPoints.Length)
- {
- if (_condition.ScreenCapturePoints == 0) break;
- for (int j = 0; j < _condition.ScreenCapturePoints; j++)
- {
- updatedIndexes[j] = i;
- int x = (int)(_capturedPoints[i].X * (double)_condition.Width) - _condition.PixelDensityX / 2;
- int y = (int)(_capturedPoints[i].Y * (double)_condition.Height) - _condition.PixelDensityY / 2;
- x = (x >= _condition.Width - _condition.PixelDensityX) ? _condition.Width - (_condition.PixelDensityX + 1) : x;
- y = (y >= _condition.Height - _condition.PixelDensityY) ? (_condition.Height - _condition.PixelDensityY + 1) : y;
- int res;
- if (!IsTizen7OrHigher)
- {
- res = MeasurePosition(j, x, y);
- } else
- {
- res = MeasurePosition7(j, x, y);
- }
-
- i++;
- if (res < 0)
- {
- // This should not happen, handle it.
- }
- }
-
- if (_condition.SleepMS > 0)
- {
- Thread.Sleep(_condition.SleepMS);
- }
- int k = 0;
- while (k < _condition.ScreenCapturePoints)
- {
- Color color;
-
- int res;
-
- if (!IsTizen7OrHigher)
- {
- res = MeasurePixel(k, out color);
- } else
- {
- res = MeasurePixel7(k, out color);
- }
-
- if (res < 0)
- {
- // This should not happen, handle it.
- } else
- {
- bool invalidColorData = color.R > 1023 || color.G > 1023 || color.B > 1023;
-
- if (invalidColorData)
- {
- // This should not happen, handle it.
- } else
- {
- colorData[i - _condition.ScreenCapturePoints + k] = color;
- k++;
- }
- }
- }
- }
- return colorData;
- }
-
- public static string ToImage(Color[] colors)
- {
- using (var image = new SKBitmap(64, 48))
- {
- for (int x = 0; x < 64; x++)
- {
- Color color = colors[x / 16];
- SKColor sKColor = ClampColor(color);
- for (int y = 0; y < 4; y++)
- {
- image.SetPixel(x, y, sKColor);
- }
- }
-
- for (int x = 0; x < 64; x++)
- {
- Color color = colors[x / 16 + 7];
- SKColor sKColor = ClampColor(color);
- for (int y = 44; y < 48; y++)
- {
- image.SetPixel(x, y, sKColor);
- }
- }
-
- for (int y = 0; y < 48; y++)
- {
- Color color = colors[11 + y / 16];
- SKColor sKColor = ClampColor(color);
- for (int x = 0; x < 3; x++)
- {
- image.SetPixel(x, y, sKColor);
- }
- }
-
- for (int y = 0; y < 48; y++)
- {
- Color color = colors[4 + y / 16];
- SKColor sKColor = ClampColor(color);
- for (int x = 61; x < 64; x++)
- {
- image.SetPixel(x, y, sKColor);
- }
- }
-
- using (var memoryStream = new MemoryStream())
- {
- using (var data = SKImage.FromBitmap(image).Encode(SKEncodedImageFormat.Png, 100))
- {
- data.SaveTo(memoryStream);
- }
- byte[] imageBytes = memoryStream.ToArray();
- string base64String = Convert.ToBase64String(imageBytes);
- return base64String;
- }
- }
- }
-
- static SKColor ClampColor(Color color)
- {
- byte r = (byte)Math.Min(color.R, 255);
- byte g = (byte)Math.Min(color.G, 255);
- byte b = (byte)Math.Min(color.B, 255);
- return new SKColor(r, g, b);
- }
- }
-
- public struct Color
- {
- public int R;
- public int G;
- public int B;
- }
-
- public struct Condition
- {
- public int ScreenCapturePoints;
-
- public int PixelDensityX;
-
- public int PixelDensityY;
-
- public int SleepMS;
-
- public int Width;
-
- public int Height;
- }
-
- public struct CapturePoint
- {
- public CapturePoint(double x, double y) {
- this.X = x;
- this.Y = y;
- }
-
- public double X;
- public double Y;
- }
-}
diff --git a/HyperTizen/Directory.Build.targets b/HyperTizen/Directory.Build.targets
index 3e8f209..cf6c1a9 100644
--- a/HyperTizen/Directory.Build.targets
+++ b/HyperTizen/Directory.Build.targets
@@ -1,21 +1,21 @@
-
-
-
-
-
-
-
- $([System.IO.Path]::GetDirectoryName($(MSBuildProjectDirectory)))
-
-
-
-
-
-
+
+
+
+
+
+
+
+ $([System.IO.Path]::GetDirectoryName($(MSBuildProjectDirectory)))
+
+
+
+
+
+
diff --git a/HyperTizen/Flatbuffers/Clear.cs b/HyperTizen/Flatbuffers/Clear.cs
new file mode 100644
index 0000000..2f56c4c
--- /dev/null
+++ b/HyperTizen/Flatbuffers/Clear.cs
@@ -0,0 +1,50 @@
+//
+// automatically generated by the FlatBuffers compiler, do not modify
+//
+
+namespace hyperhdrnet
+{
+
+using global::System;
+using global::System.Collections.Generic;
+using global::Google.FlatBuffers;
+
+public struct Clear : IFlatbufferObject
+{
+ private Table __p;
+ public ByteBuffer ByteBuffer { get { return __p.bb; } }
+ public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); }
+ public static Clear GetRootAsClear(ByteBuffer _bb) { return GetRootAsClear(_bb, new Clear()); }
+ public static Clear GetRootAsClear(ByteBuffer _bb, Clear obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
+ public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
+ public Clear __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
+
+ public int Priority { get { int o = __p.__offset(4); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)0; } }
+
+ public static Offset CreateClear(FlatBufferBuilder builder,
+ int priority = 0) {
+ builder.StartTable(1);
+ Clear.AddPriority(builder, priority);
+ return Clear.EndClear(builder);
+ }
+
+ public static void StartClear(FlatBufferBuilder builder) { builder.StartTable(1); }
+ public static void AddPriority(FlatBufferBuilder builder, int priority) { builder.AddInt(0, priority, 0); }
+ public static Offset EndClear(FlatBufferBuilder builder) {
+ int o = builder.EndTable();
+ return new Offset(o);
+ }
+}
+
+
+static public class ClearVerify
+{
+ static public bool Verify(Google.FlatBuffers.Verifier verifier, uint tablePos)
+ {
+ return verifier.VerifyTableStart(tablePos)
+ && verifier.VerifyField(tablePos, 4 /*Priority*/, 4 /*int*/, 4, false)
+ && verifier.VerifyTableEnd(tablePos);
+ }
+}
+
+}
diff --git a/HyperTizen/Flatbuffers/Color.cs b/HyperTizen/Flatbuffers/Color.cs
new file mode 100644
index 0000000..ca062f9
--- /dev/null
+++ b/HyperTizen/Flatbuffers/Color.cs
@@ -0,0 +1,55 @@
+//
+// automatically generated by the FlatBuffers compiler, do not modify
+//
+
+namespace hyperhdrnet
+{
+
+using global::System;
+using global::System.Collections.Generic;
+using global::Google.FlatBuffers;
+
+public struct Color : IFlatbufferObject
+{
+ private Table __p;
+ public ByteBuffer ByteBuffer { get { return __p.bb; } }
+ public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); }
+ public static Color GetRootAsColor(ByteBuffer _bb) { return GetRootAsColor(_bb, new Color()); }
+ public static Color GetRootAsColor(ByteBuffer _bb, Color obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
+ public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
+ public Color __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
+
+ public int Data { get { int o = __p.__offset(4); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)-1; } }
+ public int Duration { get { int o = __p.__offset(6); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)-1; } }
+
+ public static Offset CreateColor(FlatBufferBuilder builder,
+ int data = -1,
+ int duration = -1) {
+ builder.StartTable(2);
+ Color.AddDuration(builder, duration);
+ Color.AddData(builder, data);
+ return Color.EndColor(builder);
+ }
+
+ public static void StartColor(FlatBufferBuilder builder) { builder.StartTable(2); }
+ public static void AddData(FlatBufferBuilder builder, int data) { builder.AddInt(0, data, -1); }
+ public static void AddDuration(FlatBufferBuilder builder, int duration) { builder.AddInt(1, duration, -1); }
+ public static Offset EndColor(FlatBufferBuilder builder) {
+ int o = builder.EndTable();
+ return new Offset(o);
+ }
+}
+
+
+static public class ColorVerify
+{
+ static public bool Verify(Google.FlatBuffers.Verifier verifier, uint tablePos)
+ {
+ return verifier.VerifyTableStart(tablePos)
+ && verifier.VerifyField(tablePos, 4 /*Data*/, 4 /*int*/, 4, false)
+ && verifier.VerifyField(tablePos, 6 /*Duration*/, 4 /*int*/, 4, false)
+ && verifier.VerifyTableEnd(tablePos);
+ }
+}
+
+}
diff --git a/HyperTizen/Flatbuffers/Command.cs b/HyperTizen/Flatbuffers/Command.cs
new file mode 100644
index 0000000..e3c99af
--- /dev/null
+++ b/HyperTizen/Flatbuffers/Command.cs
@@ -0,0 +1,46 @@
+//
+// automatically generated by the FlatBuffers compiler, do not modify
+//
+
+namespace hyperhdrnet
+{
+
+public enum Command : byte
+{
+ NONE = 0,
+ Color = 1,
+ Image = 2,
+ Clear = 3,
+ Register = 4,
+};
+
+
+
+static public class CommandVerify
+{
+ static public bool Verify(Google.FlatBuffers.Verifier verifier, byte typeId, uint tablePos)
+ {
+ bool result = true;
+ switch((Command)typeId)
+ {
+ case Command.Color:
+ result = hyperhdrnet.ColorVerify.Verify(verifier, tablePos);
+ break;
+ case Command.Image:
+ result = hyperhdrnet.ImageVerify.Verify(verifier, tablePos);
+ break;
+ case Command.Clear:
+ result = hyperhdrnet.ClearVerify.Verify(verifier, tablePos);
+ break;
+ case Command.Register:
+ result = hyperhdrnet.RegisterVerify.Verify(verifier, tablePos);
+ break;
+ default: result = true;
+ break;
+ }
+ return result;
+ }
+}
+
+
+}
diff --git a/HyperTizen/Flatbuffers/Image.cs b/HyperTizen/Flatbuffers/Image.cs
new file mode 100644
index 0000000..989e803
--- /dev/null
+++ b/HyperTizen/Flatbuffers/Image.cs
@@ -0,0 +1,63 @@
+//
+// automatically generated by the FlatBuffers compiler, do not modify
+//
+
+namespace hyperhdrnet
+{
+
+using global::System;
+using global::System.Collections.Generic;
+using global::Google.FlatBuffers;
+
+public struct Image : IFlatbufferObject
+{
+ private Table __p;
+ public ByteBuffer ByteBuffer { get { return __p.bb; } }
+ public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); }
+ public static Image GetRootAsImage(ByteBuffer _bb) { return GetRootAsImage(_bb, new Image()); }
+ public static Image GetRootAsImage(ByteBuffer _bb, Image obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
+ public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
+ public Image __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
+
+ public hyperhdrnet.ImageType DataType { get { int o = __p.__offset(4); return o != 0 ? (hyperhdrnet.ImageType)__p.bb.Get(o + __p.bb_pos) : hyperhdrnet.ImageType.NONE; } }
+ public TTable? Data() where TTable : struct, IFlatbufferObject { int o = __p.__offset(6); return o != 0 ? (TTable?)__p.__union(o + __p.bb_pos) : null; }
+ public hyperhdrnet.RawImage DataAsRawImage() { return Data().Value; }
+ public hyperhdrnet.NV12Image DataAsNV12Image() { return Data().Value; }
+ public int Duration { get { int o = __p.__offset(8); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)-1; } }
+
+ public static Offset CreateImage(FlatBufferBuilder builder,
+ hyperhdrnet.ImageType data_type = hyperhdrnet.ImageType.NONE,
+ int dataOffset = 0,
+ int duration = -1) {
+ builder.StartTable(3);
+ Image.AddDuration(builder, duration);
+ Image.AddData(builder, dataOffset);
+ Image.AddDataType(builder, data_type);
+ return Image.EndImage(builder);
+ }
+
+ public static void StartImage(FlatBufferBuilder builder) { builder.StartTable(3); }
+ public static void AddDataType(FlatBufferBuilder builder, hyperhdrnet.ImageType dataType) { builder.AddByte(0, (byte)dataType, 0); }
+ public static void AddData(FlatBufferBuilder builder, int dataOffset) { builder.AddOffset(1, dataOffset, 0); }
+ public static void AddDuration(FlatBufferBuilder builder, int duration) { builder.AddInt(2, duration, -1); }
+ public static Offset EndImage(FlatBufferBuilder builder) {
+ int o = builder.EndTable();
+ builder.Required(o, 6); // data
+ return new Offset(o);
+ }
+}
+
+
+static public class ImageVerify
+{
+ static public bool Verify(Google.FlatBuffers.Verifier verifier, uint tablePos)
+ {
+ return verifier.VerifyTableStart(tablePos)
+ && verifier.VerifyField(tablePos, 4 /*DataType*/, 1 /*hyperhdrnet.ImageType*/, 1, false)
+ && verifier.VerifyUnion(tablePos, 4, 6 /*Data*/, hyperhdrnet.ImageTypeVerify.Verify, true)
+ && verifier.VerifyField(tablePos, 8 /*Duration*/, 4 /*int*/, 4, false)
+ && verifier.VerifyTableEnd(tablePos);
+ }
+}
+
+}
diff --git a/HyperTizen/Flatbuffers/ImageType.cs b/HyperTizen/Flatbuffers/ImageType.cs
new file mode 100644
index 0000000..f81a569
--- /dev/null
+++ b/HyperTizen/Flatbuffers/ImageType.cs
@@ -0,0 +1,38 @@
+//
+// automatically generated by the FlatBuffers compiler, do not modify
+//
+
+namespace hyperhdrnet
+{
+
+public enum ImageType : byte
+{
+ NONE = 0,
+ RawImage = 1,
+ NV12Image = 2,
+};
+
+
+
+static public class ImageTypeVerify
+{
+ static public bool Verify(Google.FlatBuffers.Verifier verifier, byte typeId, uint tablePos)
+ {
+ bool result = true;
+ switch((ImageType)typeId)
+ {
+ case ImageType.RawImage:
+ result = hyperhdrnet.RawImageVerify.Verify(verifier, tablePos);
+ break;
+ case ImageType.NV12Image:
+ result = hyperhdrnet.NV12ImageVerify.Verify(verifier, tablePos);
+ break;
+ default: result = true;
+ break;
+ }
+ return result;
+ }
+}
+
+
+}
diff --git a/HyperTizen/Flatbuffers/NV12Image.cs b/HyperTizen/Flatbuffers/NV12Image.cs
new file mode 100644
index 0000000..1931eee
--- /dev/null
+++ b/HyperTizen/Flatbuffers/NV12Image.cs
@@ -0,0 +1,99 @@
+//
+// automatically generated by the FlatBuffers compiler, do not modify
+//
+
+namespace hyperhdrnet
+{
+
+using global::System;
+using global::System.Collections.Generic;
+using global::Google.FlatBuffers;
+
+public struct NV12Image : IFlatbufferObject
+{
+ private Table __p;
+ public ByteBuffer ByteBuffer { get { return __p.bb; } }
+ public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); }
+ public static NV12Image GetRootAsNV12Image(ByteBuffer _bb) { return GetRootAsNV12Image(_bb, new NV12Image()); }
+ public static NV12Image GetRootAsNV12Image(ByteBuffer _bb, NV12Image obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
+ public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
+ public NV12Image __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
+
+ public byte DataY(int j) { int o = __p.__offset(4); return o != 0 ? __p.bb.Get(__p.__vector(o) + j * 1) : (byte)0; }
+ public int DataYLength { get { int o = __p.__offset(4); return o != 0 ? __p.__vector_len(o) : 0; } }
+#if ENABLE_SPAN_T
+ public Span GetDataYBytes() { return __p.__vector_as_span(4, 1); }
+#else
+ public ArraySegment? GetDataYBytes() { return __p.__vector_as_arraysegment(4); }
+#endif
+ public byte[] GetDataYArray() { return __p.__vector_as_array(4); }
+ public byte DataUv(int j) { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(__p.__vector(o) + j * 1) : (byte)0; }
+ public int DataUvLength { get { int o = __p.__offset(6); return o != 0 ? __p.__vector_len(o) : 0; } }
+#if ENABLE_SPAN_T
+ public Span GetDataUvBytes() { return __p.__vector_as_span(6, 1); }
+#else
+ public ArraySegment? GetDataUvBytes() { return __p.__vector_as_arraysegment(6); }
+#endif
+ public byte[] GetDataUvArray() { return __p.__vector_as_array(6); }
+ public int Width { get { int o = __p.__offset(8); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)0; } }
+ public int Height { get { int o = __p.__offset(10); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)0; } }
+ public int StrideY { get { int o = __p.__offset(12); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)0; } }
+ public int StrideUv { get { int o = __p.__offset(14); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)0; } }
+
+ public static Offset CreateNV12Image(FlatBufferBuilder builder,
+ VectorOffset data_yOffset = default(VectorOffset),
+ VectorOffset data_uvOffset = default(VectorOffset),
+ int width = 0,
+ int height = 0,
+ int stride_y = 0,
+ int stride_uv = 0) {
+ builder.StartTable(6);
+ NV12Image.AddStrideUv(builder, stride_uv);
+ NV12Image.AddStrideY(builder, stride_y);
+ NV12Image.AddHeight(builder, height);
+ NV12Image.AddWidth(builder, width);
+ NV12Image.AddDataUv(builder, data_uvOffset);
+ NV12Image.AddDataY(builder, data_yOffset);
+ return NV12Image.EndNV12Image(builder);
+ }
+
+ public static void StartNV12Image(FlatBufferBuilder builder) { builder.StartTable(6); }
+ public static void AddDataY(FlatBufferBuilder builder, VectorOffset dataYOffset) { builder.AddOffset(0, dataYOffset.Value, 0); }
+ public static VectorOffset CreateDataYVector(FlatBufferBuilder builder, byte[] data) { builder.StartVector(1, data.Length, 1); for (int i = data.Length - 1; i >= 0; i--) builder.AddByte(data[i]); return builder.EndVector(); }
+ public static VectorOffset CreateDataYVectorBlock(FlatBufferBuilder builder, byte[] data) { builder.StartVector(1, data.Length, 1); builder.Add(data); return builder.EndVector(); }
+ public static VectorOffset CreateDataYVectorBlock(FlatBufferBuilder builder, ArraySegment data) { builder.StartVector(1, data.Count, 1); builder.Add(data); return builder.EndVector(); }
+ public static VectorOffset CreateDataYVectorBlock(FlatBufferBuilder builder, IntPtr dataPtr, int sizeInBytes) { builder.StartVector(1, sizeInBytes, 1); builder.Add(dataPtr, sizeInBytes); return builder.EndVector(); }
+ public static void StartDataYVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); }
+ public static void AddDataUv(FlatBufferBuilder builder, VectorOffset dataUvOffset) { builder.AddOffset(1, dataUvOffset.Value, 0); }
+ public static VectorOffset CreateDataUvVector(FlatBufferBuilder builder, byte[] data) { builder.StartVector(1, data.Length, 1); for (int i = data.Length - 1; i >= 0; i--) builder.AddByte(data[i]); return builder.EndVector(); }
+ public static VectorOffset CreateDataUvVectorBlock(FlatBufferBuilder builder, byte[] data) { builder.StartVector(1, data.Length, 1); builder.Add(data); return builder.EndVector(); }
+ public static VectorOffset CreateDataUvVectorBlock(FlatBufferBuilder builder, ArraySegment data) { builder.StartVector(1, data.Count, 1); builder.Add(data); return builder.EndVector(); }
+ public static VectorOffset CreateDataUvVectorBlock(FlatBufferBuilder builder, IntPtr dataPtr, int sizeInBytes) { builder.StartVector(1, sizeInBytes, 1); builder.Add(dataPtr, sizeInBytes); return builder.EndVector(); }
+ public static void StartDataUvVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); }
+ public static void AddWidth(FlatBufferBuilder builder, int width) { builder.AddInt(2, width, 0); }
+ public static void AddHeight(FlatBufferBuilder builder, int height) { builder.AddInt(3, height, 0); }
+ public static void AddStrideY(FlatBufferBuilder builder, int strideY) { builder.AddInt(4, strideY, 0); }
+ public static void AddStrideUv(FlatBufferBuilder builder, int strideUv) { builder.AddInt(5, strideUv, 0); }
+ public static Offset EndNV12Image(FlatBufferBuilder builder) {
+ int o = builder.EndTable();
+ return new Offset(o);
+ }
+}
+
+
+static public class NV12ImageVerify
+{
+ static public bool Verify(Google.FlatBuffers.Verifier verifier, uint tablePos)
+ {
+ return verifier.VerifyTableStart(tablePos)
+ && verifier.VerifyVectorOfData(tablePos, 4 /*DataY*/, 1 /*byte*/, false)
+ && verifier.VerifyVectorOfData(tablePos, 6 /*DataUv*/, 1 /*byte*/, false)
+ && verifier.VerifyField(tablePos, 8 /*Width*/, 4 /*int*/, 4, false)
+ && verifier.VerifyField(tablePos, 10 /*Height*/, 4 /*int*/, 4, false)
+ && verifier.VerifyField(tablePos, 12 /*StrideY*/, 4 /*int*/, 4, false)
+ && verifier.VerifyField(tablePos, 14 /*StrideUv*/, 4 /*int*/, 4, false)
+ && verifier.VerifyTableEnd(tablePos);
+ }
+}
+
+}
diff --git a/HyperTizen/Flatbuffers/RawImage.cs b/HyperTizen/Flatbuffers/RawImage.cs
new file mode 100644
index 0000000..a3e14e5
--- /dev/null
+++ b/HyperTizen/Flatbuffers/RawImage.cs
@@ -0,0 +1,72 @@
+//
+// automatically generated by the FlatBuffers compiler, do not modify
+//
+
+namespace hyperhdrnet
+{
+
+using global::System;
+using global::System.Collections.Generic;
+using global::Google.FlatBuffers;
+
+public struct RawImage : IFlatbufferObject
+{
+ private Table __p;
+ public ByteBuffer ByteBuffer { get { return __p.bb; } }
+ public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); }
+ public static RawImage GetRootAsRawImage(ByteBuffer _bb) { return GetRootAsRawImage(_bb, new RawImage()); }
+ public static RawImage GetRootAsRawImage(ByteBuffer _bb, RawImage obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
+ public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
+ public RawImage __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
+
+ public byte Data(int j) { int o = __p.__offset(4); return o != 0 ? __p.bb.Get(__p.__vector(o) + j * 1) : (byte)0; }
+ public int DataLength { get { int o = __p.__offset(4); return o != 0 ? __p.__vector_len(o) : 0; } }
+#if ENABLE_SPAN_T
+ public Span GetDataBytes() { return __p.__vector_as_span(4, 1); }
+#else
+ public ArraySegment? GetDataBytes() { return __p.__vector_as_arraysegment(4); }
+#endif
+ public byte[] GetDataArray() { return __p.__vector_as_array(4); }
+ public int Width { get { int o = __p.__offset(6); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)-1; } }
+ public int Height { get { int o = __p.__offset(8); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)-1; } }
+
+ public static Offset CreateRawImage(FlatBufferBuilder builder,
+ VectorOffset dataOffset = default(VectorOffset),
+ int width = -1,
+ int height = -1) {
+ builder.StartTable(3);
+ RawImage.AddHeight(builder, height);
+ RawImage.AddWidth(builder, width);
+ RawImage.AddData(builder, dataOffset);
+ return RawImage.EndRawImage(builder);
+ }
+
+ public static void StartRawImage(FlatBufferBuilder builder) { builder.StartTable(3); }
+ public static void AddData(FlatBufferBuilder builder, VectorOffset dataOffset) { builder.AddOffset(0, dataOffset.Value, 0); }
+ public static VectorOffset CreateDataVector(FlatBufferBuilder builder, byte[] data) { builder.StartVector(1, data.Length, 1); for (int i = data.Length - 1; i >= 0; i--) builder.AddByte(data[i]); return builder.EndVector(); }
+ public static VectorOffset CreateDataVectorBlock(FlatBufferBuilder builder, byte[] data) { builder.StartVector(1, data.Length, 1); builder.Add(data); return builder.EndVector(); }
+ public static VectorOffset CreateDataVectorBlock(FlatBufferBuilder builder, ArraySegment data) { builder.StartVector(1, data.Count, 1); builder.Add(data); return builder.EndVector(); }
+ public static VectorOffset CreateDataVectorBlock(FlatBufferBuilder builder, IntPtr dataPtr, int sizeInBytes) { builder.StartVector(1, sizeInBytes, 1); builder.Add(dataPtr, sizeInBytes); return builder.EndVector(); }
+ public static void StartDataVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); }
+ public static void AddWidth(FlatBufferBuilder builder, int width) { builder.AddInt(1, width, -1); }
+ public static void AddHeight(FlatBufferBuilder builder, int height) { builder.AddInt(2, height, -1); }
+ public static Offset EndRawImage(FlatBufferBuilder builder) {
+ int o = builder.EndTable();
+ return new Offset(o);
+ }
+}
+
+
+static public class RawImageVerify
+{
+ static public bool Verify(Google.FlatBuffers.Verifier verifier, uint tablePos)
+ {
+ return verifier.VerifyTableStart(tablePos)
+ && verifier.VerifyVectorOfData(tablePos, 4 /*Data*/, 1 /*byte*/, false)
+ && verifier.VerifyField(tablePos, 6 /*Width*/, 4 /*int*/, 4, false)
+ && verifier.VerifyField(tablePos, 8 /*Height*/, 4 /*int*/, 4, false)
+ && verifier.VerifyTableEnd(tablePos);
+ }
+}
+
+}
diff --git a/HyperTizen/Flatbuffers/Register.cs b/HyperTizen/Flatbuffers/Register.cs
new file mode 100644
index 0000000..c6d4e32
--- /dev/null
+++ b/HyperTizen/Flatbuffers/Register.cs
@@ -0,0 +1,62 @@
+//
+// automatically generated by the FlatBuffers compiler, do not modify
+//
+
+namespace hyperhdrnet
+{
+
+using global::System;
+using global::System.Collections.Generic;
+using global::Google.FlatBuffers;
+
+public struct Register : IFlatbufferObject
+{
+ private Table __p;
+ public ByteBuffer ByteBuffer { get { return __p.bb; } }
+ public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); }
+ public static Register GetRootAsRegister(ByteBuffer _bb) { return GetRootAsRegister(_bb, new Register()); }
+ public static Register GetRootAsRegister(ByteBuffer _bb, Register obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
+ public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
+ public Register __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
+
+ public string Origin { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
+#if ENABLE_SPAN_T
+ public Span GetOriginBytes() { return __p.__vector_as_span(4, 1); }
+#else
+ public ArraySegment? GetOriginBytes() { return __p.__vector_as_arraysegment(4); }
+#endif
+ public byte[] GetOriginArray() { return __p.__vector_as_array(4); }
+ public int Priority { get { int o = __p.__offset(6); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)0; } }
+
+ public static Offset CreateRegister(FlatBufferBuilder builder,
+ StringOffset originOffset = default(StringOffset),
+ int priority = 0) {
+ builder.StartTable(2);
+ Register.AddPriority(builder, priority);
+ Register.AddOrigin(builder, originOffset);
+ return Register.EndRegister(builder);
+ }
+
+ public static void StartRegister(FlatBufferBuilder builder) { builder.StartTable(2); }
+ public static void AddOrigin(FlatBufferBuilder builder, StringOffset originOffset) { builder.AddOffset(0, originOffset.Value, 0); }
+ public static void AddPriority(FlatBufferBuilder builder, int priority) { builder.AddInt(1, priority, 0); }
+ public static Offset EndRegister(FlatBufferBuilder builder) {
+ int o = builder.EndTable();
+ builder.Required(o, 4); // origin
+ return new Offset(o);
+ }
+}
+
+
+static public class RegisterVerify
+{
+ static public bool Verify(Google.FlatBuffers.Verifier verifier, uint tablePos)
+ {
+ return verifier.VerifyTableStart(tablePos)
+ && verifier.VerifyString(tablePos, 4 /*Origin*/, true)
+ && verifier.VerifyField(tablePos, 6 /*Priority*/, 4 /*int*/, 4, false)
+ && verifier.VerifyTableEnd(tablePos);
+ }
+}
+
+}
diff --git a/HyperTizen/Flatbuffers/Reply.cs b/HyperTizen/Flatbuffers/Reply.cs
new file mode 100644
index 0000000..5f9d88a
--- /dev/null
+++ b/HyperTizen/Flatbuffers/Reply.cs
@@ -0,0 +1,69 @@
+//
+// automatically generated by the FlatBuffers compiler, do not modify
+//
+
+namespace hyperhdrnet
+{
+
+using global::System;
+using global::System.Collections.Generic;
+using global::Google.FlatBuffers;
+
+public struct Reply : IFlatbufferObject
+{
+ private Table __p;
+ public ByteBuffer ByteBuffer { get { return __p.bb; } }
+ public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); }
+ public static Reply GetRootAsReply(ByteBuffer _bb) { return GetRootAsReply(_bb, new Reply()); }
+ public static Reply GetRootAsReply(ByteBuffer _bb, Reply obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
+ public static bool VerifyReply(ByteBuffer _bb) {Google.FlatBuffers.Verifier verifier = new Google.FlatBuffers.Verifier(_bb); return verifier.VerifyBuffer("", false, ReplyVerify.Verify); }
+ public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
+ public Reply __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
+
+ public string Error { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
+#if ENABLE_SPAN_T
+ public Span GetErrorBytes() { return __p.__vector_as_span(4, 1); }
+#else
+ public ArraySegment? GetErrorBytes() { return __p.__vector_as_arraysegment(4); }
+#endif
+ public byte[] GetErrorArray() { return __p.__vector_as_array(4); }
+ public int Video { get { int o = __p.__offset(6); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)-1; } }
+ public int Registered { get { int o = __p.__offset(8); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)-1; } }
+
+ public static Offset CreateReply(FlatBufferBuilder builder,
+ StringOffset errorOffset = default(StringOffset),
+ int video = -1,
+ int registered = -1) {
+ builder.StartTable(3);
+ Reply.AddRegistered(builder, registered);
+ Reply.AddVideo(builder, video);
+ Reply.AddError(builder, errorOffset);
+ return Reply.EndReply(builder);
+ }
+
+ public static void StartReply(FlatBufferBuilder builder) { builder.StartTable(3); }
+ public static void AddError(FlatBufferBuilder builder, StringOffset errorOffset) { builder.AddOffset(0, errorOffset.Value, 0); }
+ public static void AddVideo(FlatBufferBuilder builder, int video) { builder.AddInt(1, video, -1); }
+ public static void AddRegistered(FlatBufferBuilder builder, int registered) { builder.AddInt(2, registered, -1); }
+ public static Offset EndReply(FlatBufferBuilder builder) {
+ int o = builder.EndTable();
+ return new Offset(o);
+ }
+ public static void FinishReplyBuffer(FlatBufferBuilder builder, Offset offset) { builder.Finish(offset.Value); }
+ public static void FinishSizePrefixedReplyBuffer(FlatBufferBuilder builder, Offset offset) { builder.FinishSizePrefixed(offset.Value); }
+}
+
+
+static public class ReplyVerify
+{
+ static public bool Verify(Google.FlatBuffers.Verifier verifier, uint tablePos)
+ {
+ return verifier.VerifyTableStart(tablePos)
+ && verifier.VerifyString(tablePos, 4 /*Error*/, false)
+ && verifier.VerifyField(tablePos, 6 /*Video*/, 4 /*int*/, 4, false)
+ && verifier.VerifyField(tablePos, 8 /*Registered*/, 4 /*int*/, 4, false)
+ && verifier.VerifyTableEnd(tablePos);
+ }
+}
+
+}
diff --git a/HyperTizen/Flatbuffers/Request.cs b/HyperTizen/Flatbuffers/Request.cs
new file mode 100644
index 0000000..6f26360
--- /dev/null
+++ b/HyperTizen/Flatbuffers/Request.cs
@@ -0,0 +1,63 @@
+//
+// automatically generated by the FlatBuffers compiler, do not modify
+//
+
+namespace hyperhdrnet
+{
+
+using global::System;
+using global::System.Collections.Generic;
+using global::Google.FlatBuffers;
+
+public struct Request : IFlatbufferObject
+{
+ private Table __p;
+ public ByteBuffer ByteBuffer { get { return __p.bb; } }
+ public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_25_2_10(); }
+ public static Request GetRootAsRequest(ByteBuffer _bb) { return GetRootAsRequest(_bb, new Request()); }
+ public static Request GetRootAsRequest(ByteBuffer _bb, Request obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
+ public static bool VerifyRequest(ByteBuffer _bb) {Google.FlatBuffers.Verifier verifier = new Google.FlatBuffers.Verifier(_bb); return verifier.VerifyBuffer("", false, RequestVerify.Verify); }
+ public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
+ public Request __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
+
+ public hyperhdrnet.Command CommandType { get { int o = __p.__offset(4); return o != 0 ? (hyperhdrnet.Command)__p.bb.Get(o + __p.bb_pos) : hyperhdrnet.Command.NONE; } }
+ public TTable? Command() where TTable : struct, IFlatbufferObject { int o = __p.__offset(6); return o != 0 ? (TTable?)__p.__union(o + __p.bb_pos) : null; }
+ public hyperhdrnet.Color CommandAsColor() { return Command().Value; }
+ public hyperhdrnet.Image CommandAsImage() { return Command().Value; }
+ public hyperhdrnet.Clear CommandAsClear() { return Command().Value; }
+ public hyperhdrnet.Register CommandAsRegister() { return Command().Value; }
+
+ public static Offset CreateRequest(FlatBufferBuilder builder,
+ hyperhdrnet.Command command_type = hyperhdrnet.Command.NONE,
+ int commandOffset = 0) {
+ builder.StartTable(2);
+ Request.AddCommand(builder, commandOffset);
+ Request.AddCommandType(builder, command_type);
+ return Request.EndRequest(builder);
+ }
+
+ public static void StartRequest(FlatBufferBuilder builder) { builder.StartTable(2); }
+ public static void AddCommandType(FlatBufferBuilder builder, hyperhdrnet.Command commandType) { builder.AddByte(0, (byte)commandType, 0); }
+ public static void AddCommand(FlatBufferBuilder builder, int commandOffset) { builder.AddOffset(1, commandOffset, 0); }
+ public static Offset EndRequest(FlatBufferBuilder builder) {
+ int o = builder.EndTable();
+ builder.Required(o, 6); // command
+ return new Offset(o);
+ }
+ public static void FinishRequestBuffer(FlatBufferBuilder builder, Offset offset) { builder.Finish(offset.Value); }
+ public static void FinishSizePrefixedRequestBuffer(FlatBufferBuilder builder, Offset offset) { builder.FinishSizePrefixed(offset.Value); }
+}
+
+
+static public class RequestVerify
+{
+ static public bool Verify(Google.FlatBuffers.Verifier verifier, uint tablePos)
+ {
+ return verifier.VerifyTableStart(tablePos)
+ && verifier.VerifyField(tablePos, 4 /*CommandType*/, 1 /*hyperhdrnet.Command*/, 1, false)
+ && verifier.VerifyUnion(tablePos, 4, 6 /*Command*/, hyperhdrnet.CommandVerify.Verify, true)
+ && verifier.VerifyTableEnd(tablePos);
+ }
+}
+
+}
diff --git a/HyperTizen/Globals.cs b/HyperTizen/Globals.cs
new file mode 100644
index 0000000..270cea1
--- /dev/null
+++ b/HyperTizen/Globals.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tizen.Applications;
+
+namespace HyperTizen
+{
+ public sealed class Globals
+ {
+ private static readonly Globals instance = new Globals();
+
+ // Explicit static constructor to tell C# compiler
+ // not to mark type as beforefieldinit
+ static Globals()
+ {
+ }
+
+ private Globals()
+ {
+ }
+
+ public static Globals Instance
+ {
+ get
+ {
+ return instance;
+ }
+ }
+ public void SetConfig()
+ {
+ (string ip, int port) = Helper.SsdpDiscovery.GetHyperIpAndPort();
+ ServerIp = ip; //ServerIp = "192.168.69.200";
+ ServerPort = port; //ServerPort = 19400;
+
+ Enabled = true;//bool.Parse(Preference.Get("enabled"));
+ Width = 3840/8;
+ Height = 2160/8;
+ }
+
+ public string ServerIp; //IP of hyperhdr server
+ public int ServerPort; //Port of hyperhdr server
+ public int Width; //Capture Width
+ public int Height; //Capture Height
+ public bool Enabled; //Is the service enabled
+ }
+}
diff --git a/HyperTizen/Helper/Log.cs b/HyperTizen/Helper/Log.cs
new file mode 100644
index 0000000..07da707
--- /dev/null
+++ b/HyperTizen/Helper/Log.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tizen.Applications.Notifications;
+
+namespace HyperTizen.Helper
+{
+ public enum eLogType
+ {
+ Debug,
+ Info,
+ Warning,
+ Error,
+ Performance
+ }
+ public static class Log
+ {
+ public static void Write(eLogType type,string message)
+ {
+ switch (type)
+ {
+ case eLogType.Debug:
+ Debug.WriteLine(message);
+ break;
+ case eLogType.Info:
+ //Debug.WriteLine(message);
+ break;
+ case eLogType.Warning:
+ Debug.WriteLine(message);
+ break;
+ case eLogType.Error:
+ Debug.WriteLine(message);
+ {
+ Notification notification = new Notification
+ {
+ Title = "HyperTizen Error!",
+ Content = message,
+ Count = 1
+ };
+ NotificationManager.Post(notification);
+ }
+ break;
+ case eLogType.Performance:
+ //Debug.WriteLine(message);
+ break;
+ }
+
+ }
+ }
+}
diff --git a/HyperTizen/Helper/SsdpDiscovery.cs b/HyperTizen/Helper/SsdpDiscovery.cs
new file mode 100644
index 0000000..a2b0253
--- /dev/null
+++ b/HyperTizen/Helper/SsdpDiscovery.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace HyperTizen.Helper
+{
+ public static class SsdpDiscovery
+ {
+ public static (string ip, int port) GetHyperIpAndPort()
+ {
+ string searchTarget = "urn:hyperhdr.eu:device:basic:1";
+ string ssdpRequest =
+$@"M-SEARCH * HTTP/1.1
+HOST: 239.255.255.250:1900
+MAN: ""ssdp:discover""
+MX: 2
+ST: {searchTarget}
+
+";
+
+ try
+ {
+ using (UdpClient udpClient = new UdpClient())
+ {
+ udpClient.Client.ReceiveTimeout = 5000;
+
+ IPEndPoint multicastEndpoint = new IPEndPoint(IPAddress.Parse("239.255.255.250"), 1900);
+ byte[] requestBytes = Encoding.UTF8.GetBytes(ssdpRequest.Replace("\n", "\r\n"));
+
+ udpClient.Send(requestBytes, requestBytes.Length, multicastEndpoint);
+
+ DateTime start = DateTime.Now;
+ TimeSpan timeout = TimeSpan.FromSeconds(5);
+
+ while (DateTime.Now - start < timeout)
+ {
+ if (udpClient.Available > 0)
+ {
+ IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);
+ byte[] responseBytes = udpClient.Receive(ref remoteEP);
+ string response = Encoding.UTF8.GetString(responseBytes);
+
+ if (response.ToLower().Contains(searchTarget.ToLower()))
+ {
+ Match locationMatch = Regex.Match(response, @"LOCATION:\s*(http://[^\s]+)", RegexOptions.IgnoreCase);
+ Match portMatch = Regex.Match(response, @"HYPERHDR-FBS-PORT:\s*(\d+)", RegexOptions.IgnoreCase);
+
+ if (locationMatch.Success && portMatch.Success)
+ {
+ Uri locationUri = new Uri(locationMatch.Groups[1].Value);
+ string ip = locationUri.Host;
+ int port = int.Parse(portMatch.Groups[1].Value);
+ return (ip, port);
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Helper.Log.Write(Helper.eLogType.Error, "SsdpDiscovery.GetHyperIpAndPort() Exception: " + ex.Message);
+ }
+
+ return (null, 0);
+ }
+ }
+}
\ No newline at end of file
diff --git a/HyperTizen/HyperTizen.csproj b/HyperTizen/HyperTizen.csproj
index 327e540..173dfb1 100644
--- a/HyperTizen/HyperTizen.csproj
+++ b/HyperTizen/HyperTizen.csproj
@@ -4,6 +4,7 @@
Exe
tizen90
+ true
@@ -19,9 +20,11 @@
+
+
diff --git a/HyperTizen/HyperTizen.csproj.user b/HyperTizen/HyperTizen.csproj.user
new file mode 100644
index 0000000..0f14913
--- /dev/null
+++ b/HyperTizen/HyperTizen.csproj.user
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/HyperTizen/HyperTizen_App.cs b/HyperTizen/HyperTizen_App.cs
index f3e148c..0903473 100644
--- a/HyperTizen/HyperTizen_App.cs
+++ b/HyperTizen/HyperTizen_App.cs
@@ -1,80 +1,76 @@
-using Tizen.Applications;
-using Tizen.Applications.Notifications;
-using Tizen.System;
-using HyperTizen.WebSocket;
-using System.Threading.Tasks;
-
-namespace HyperTizen
-{
- class App : ServiceApplication
- {
- public static HyperionClient client;
- protected override void OnCreate()
- {
- base.OnCreate();
- if (!Preference.Contains("enabled")) Preference.Set("enabled", "false");
- Task.Run(() => WebSocketServer.StartServerAsync());
- Display.StateChanged += Display_StateChanged;
- client = new HyperionClient();
- }
-
- private void Display_StateChanged(object sender, DisplayStateChangedEventArgs e)
- {
- if (e.State == DisplayState.Off)
- {
- Task.Run(() => client.Stop());
- } else if (e.State == DisplayState.Normal)
- {
- Configuration.Enabled = bool.Parse(Preference.Get("enabled"));
- Task.Run(() => client.Start());
- }
- }
-
- protected override void OnAppControlReceived(AppControlReceivedEventArgs e)
- {
- base.OnAppControlReceived(e);
- }
-
- protected override void OnDeviceOrientationChanged(DeviceOrientationEventArgs e)
- {
- base.OnDeviceOrientationChanged(e);
- }
-
- protected override void OnLocaleChanged(LocaleChangedEventArgs e)
- {
- base.OnLocaleChanged(e);
- }
-
- protected override void OnLowBattery(LowBatteryEventArgs e)
- {
- base.OnLowBattery(e);
- }
-
- protected override void OnLowMemory(LowMemoryEventArgs e)
- {
- base.OnLowMemory(e);
- }
-
- protected override void OnRegionFormatChanged(RegionFormatChangedEventArgs e)
- {
- base.OnRegionFormatChanged(e);
- }
-
- protected override void OnTerminate()
- {
- base.OnTerminate();
- }
-
- static void Main(string[] args)
- {
- App app = new App();
- app.Run(args);
- }
-
- public static class Configuration
- {
- public static string RPCServer = Preference.Contains("rpcServer") ? Preference.Get("rpcServer") : null;
- public static bool Enabled = bool.Parse(Preference.Get("enabled"));
- }
- }
-}
+using Tizen.Applications;
+using Tizen.Applications.Notifications;
+using Tizen.System;
+using System.Threading.Tasks;
+
+namespace HyperTizen
+{
+ class App : ServiceApplication
+ {
+ public static HyperionClient client;
+ protected override void OnCreate()
+ {
+ base.OnCreate();
+ if (!Preference.Contains("enabled")) Preference.Set("enabled", "false");
+ Display.StateChanged += Display_StateChanged;
+ client = new HyperionClient();
+ }
+
+ private void Display_StateChanged(object sender, DisplayStateChangedEventArgs e)
+ {
+ if (e.State == DisplayState.Off)
+ {
+ Task.Run(() => client.Stop());
+ } else if (e.State == DisplayState.Normal)
+ {
+ Task.Run(() => client.Start());
+ }
+ }
+
+ protected override void OnAppControlReceived(AppControlReceivedEventArgs e)
+ {
+ base.OnAppControlReceived(e);
+ }
+
+ protected override void OnDeviceOrientationChanged(DeviceOrientationEventArgs e)
+ {
+ base.OnDeviceOrientationChanged(e);
+ }
+
+ protected override void OnLocaleChanged(LocaleChangedEventArgs e)
+ {
+ base.OnLocaleChanged(e);
+ }
+
+ protected override void OnLowBattery(LowBatteryEventArgs e)
+ {
+ base.OnLowBattery(e);
+ }
+
+ protected override void OnLowMemory(LowMemoryEventArgs e)
+ {
+ base.OnLowMemory(e);
+ }
+
+ protected override void OnRegionFormatChanged(RegionFormatChangedEventArgs e)
+ {
+ base.OnRegionFormatChanged(e);
+ }
+
+ protected override void OnTerminate()
+ {
+ base.OnTerminate();
+ }
+
+ static void Main(string[] args)
+ {
+ App app = new App();
+ app.Run(args);
+ }
+ public static class Configuration
+ {
+ public static string RPCServer = Preference.Contains("rpcServer") ? Preference.Get("rpcServer") : null;
+ public static bool Enabled = bool.Parse(Preference.Get("enabled"));
+ }
+ }
+}
diff --git a/HyperTizen/HyperionClient.cs b/HyperTizen/HyperionClient.cs
new file mode 100644
index 0000000..562a00c
--- /dev/null
+++ b/HyperTizen/HyperionClient.cs
@@ -0,0 +1,59 @@
+using Newtonsoft.Json;
+using System.Threading.Tasks;
+using Tizen.Applications;
+using System.Net.WebSockets;
+using System.Text;
+using System;
+using System.Threading;
+using System.Runtime.InteropServices;
+using SkiaSharp;
+using Tizen.NUI;
+using System.Diagnostics;
+using System.Linq;
+using Tizen.Uix.Tts;
+using System.Net.Sockets;
+using Tizen.Applications.RPCPort;
+using System.IO;
+using Tizen.Messaging.Messages;
+using System.Linq.Expressions;
+using Tizen.Applications.Notifications;
+
+namespace HyperTizen
+{
+
+ internal class HyperionClient
+ {
+ public HyperionClient()
+ {
+ Task.Run(() => Start());
+ }
+
+ public async Task Start()
+ {
+ Globals.Instance.SetConfig();
+ VideoCapture.InitCapture();
+
+ while (Globals.Instance.Enabled)
+ {
+ if(Networking.client != null && Networking.client.Client.Connected)
+ {
+ var watchFPS = System.Diagnostics.Stopwatch.StartNew();
+ await Task.Run(() =>VideoCapture.DoCapture()); //VideoCapture.DoDummyCapture();
+ watchFPS.Stop();
+ var elapsedFPS = 1 / watchFPS.Elapsed.TotalSeconds;
+ Helper.Log.Write(Helper.eLogType.Performance, "VideoCapture.DoCapture() FPS: " + elapsedFPS);
+ Helper.Log.Write(Helper.eLogType.Performance, "VideoCapture.DoCapture() elapsed ms: " + watchFPS.ElapsedMilliseconds);
+ }
+
+ else
+ await Task.Run(() => Networking.SendRegister());
+ }
+
+ }
+
+ public async Task Stop()
+ {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/HyperTizen/Networking.cs b/HyperTizen/Networking.cs
new file mode 100644
index 0000000..5bc5bf9
--- /dev/null
+++ b/HyperTizen/Networking.cs
@@ -0,0 +1,209 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading.Tasks;
+using Google.FlatBuffers;
+using hyperhdrnet;
+using Tizen.Messaging.Messages;
+
+namespace HyperTizen
+{
+ public static class Networking
+ {
+ public static TcpClient client;
+ public static NetworkStream stream;
+
+ public static void DisconnectClient()
+ {
+ if (stream != null)
+ {
+ stream.Flush();
+ stream.Close(500);
+ }
+
+ client.Close();
+ }
+
+ public static void SendRegister()
+ {
+ client = new TcpClient(Globals.Instance.ServerIp, Globals.Instance.ServerPort);
+ if (client == null)
+ return;
+ stream = Networking.client.GetStream();
+ if (stream == null)
+ return;
+ byte[] registrationMessage = Networking.CreateRegistrationMessage();
+ if (registrationMessage == null)
+ return;
+ var header = new byte[4];
+ header[0] = (byte)((registrationMessage.Length >> 24) & 0xFF);
+ header[1] = (byte)((registrationMessage.Length >> 16) & 0xFF);
+ header[2] = (byte)((registrationMessage.Length >> 8) & 0xFF);
+ header[3] = (byte)((registrationMessage.Length) & 0xFF);
+ stream.Write(header, 0, header.Length);
+ stream.Write(registrationMessage, 0, registrationMessage.Length);
+ ReadRegisterReply();
+ Helper.Log.Write(Helper.eLogType.Info, "SendRegister: Data sent");
+ }
+
+ public static async Task SendImageAsync(byte[] yData, byte[] uvData, int width, int height)
+ {
+ if (client == null || !client.Connected || stream == null)
+ return;
+ byte[] message = CreateFlatBufferMessage(yData, uvData, width, height);
+ if (message == null)
+ return;
+
+ var watchFPS = System.Diagnostics.Stopwatch.StartNew();
+ _ = SendMessageAndReceiveReplyAsync(message);
+ watchFPS.Stop();
+ Helper.Log.Write(Helper.eLogType.Performance, "SendImageAsync elapsed ms: " + watchFPS.ElapsedMilliseconds);
+ }
+ static byte[] CreateFlatBufferMessage(byte[] yData, byte[] uvData, int width, int height)
+ {
+ if (client == null || !client.Connected || stream == null)
+ return null;
+ var builder = new FlatBufferBuilder(yData.Length + uvData.Length + 100);
+
+ var yVector = NV12Image.CreateDataYVector(builder, yData);
+ var uvVector = NV12Image.CreateDataUvVector(builder, uvData);
+
+ NV12Image.StartNV12Image(builder);
+ NV12Image.AddDataY(builder, yVector);
+ NV12Image.AddDataUv(builder, uvVector);
+ NV12Image.AddWidth(builder, width);
+ NV12Image.AddHeight(builder, height);
+ NV12Image.AddStrideY(builder, width); //TODO: Check if this is correct
+ NV12Image.AddStrideUv(builder, width);
+ var nv12Image = NV12Image.EndNV12Image(builder);
+
+ Image.StartImage(builder);
+ Image.AddDataType(builder, ImageType.NV12Image);
+ Image.AddData(builder, nv12Image.Value);
+ Image.AddDuration(builder, -1);
+ var imageOffset = Image.EndImage(builder);
+
+ Request.StartRequest(builder);
+ Request.AddCommandType(builder, Command.Image);
+ Request.AddCommand(builder, imageOffset.Value);
+ var requestOffset = Request.EndRequest(builder);
+
+ builder.Finish(requestOffset.Value);
+ return builder.SizedByteArray();
+ }
+
+ static Reply ParseReply(byte[] receivedData)
+ {
+ var byteBuffer = new ByteBuffer(receivedData, 4); //shift for header
+ return Reply.GetRootAsReply(byteBuffer);
+ }
+
+ public static byte[] CreateRegistrationMessage()
+ {
+ if (client == null || !client.Connected || stream == null)
+ return null;
+
+ var builder = new FlatBufferBuilder(256); //TODO:Check how to calculate correctly
+
+ var originOffset = builder.CreateString("HyperTizen");
+
+ Register.StartRegister(builder);
+ Register.AddPriority(builder, 123);
+ Register.AddOrigin(builder, originOffset);
+ var registerOffset = Register.EndRegister(builder);
+
+ Request.StartRequest(builder);
+ Request.AddCommandType(builder, Command.Register);
+ Request.AddCommand(builder, registerOffset.Value);
+ var requestOffset = Request.EndRequest(builder);
+
+ builder.Finish(requestOffset.Value);
+ return builder.SizedByteArray();
+ }
+
+ public static void ReadRegisterReply()
+ {
+ if (client == null || !client.Connected || stream == null)
+ return;
+
+ byte[] buffer = new byte[1024];
+ int bytesRead = stream.Read(buffer, 0, buffer.Length);
+ if (bytesRead > 0)
+ {
+ byte[] replyData = new byte[bytesRead];
+ Array.Copy(buffer, replyData, bytesRead);
+
+ Reply reply = ParseReply(replyData);
+ Helper.Log.Write(Helper.eLogType.Info, $"ReadRegisterReply: Reply_Registered: {reply.Registered}");
+ }
+ }
+
+ public static async Task ReadImageReply()
+ {
+ if (client == null || !client.Connected || stream == null)
+ return;
+
+ byte[] buffer = new byte[1024];
+ int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
+ if (bytesRead > 0)
+ {
+
+ byte[] replyData = new byte[bytesRead];
+ Array.Copy(buffer, replyData, bytesRead);
+ Reply reply = ParseReply(replyData);
+
+
+ Helper.Log.Write(Helper.eLogType.Info, $"SendMessageAndReceiveReply: Reply_Video: {reply.Video}");
+ Helper.Log.Write(Helper.eLogType.Info, $"SendMessageAndReceiveReply: Reply_Registered: {reply.Registered}");
+ if (!string.IsNullOrEmpty(reply.Error))
+ {
+ Helper.Log.Write(Helper.eLogType.Error, "SendMessageAndReceiveReply: (closing tcp client now) Reply_Error: " + reply.Error);
+ //Debug.WriteLine("SendMessageAndReceiveReply: Faulty msg(size:" + message.Length + "): " + BitConverter.ToString(message));
+ DisconnectClient();
+ return;
+ }
+ }
+ else
+ {
+ Helper.Log.Write(Helper.eLogType.Error, "SendMessageAndReceiveReply: (closing tcp client now) No Answer from Server.");
+ DisconnectClient();
+ return;
+ }
+ }
+
+ static async Task SendMessageAndReceiveReplyAsync(byte[] message)
+ {
+ try
+ {
+ if (client == null || !client.Connected || stream == null)
+ return;
+ {
+
+ var header = new byte[4];
+ header[0] = (byte)((message.Length >> 24) & 0xFF);
+ header[1] = (byte)((message.Length >> 16) & 0xFF);
+ header[2] = (byte)((message.Length >> 8) & 0xFF);
+ header[3] = (byte)((message.Length) & 0xFF);
+ await stream.WriteAsync(header, 0, header.Length);
+
+ Helper.Log.Write(Helper.eLogType.Info, "SendMessageAndReceiveReply: message.Length; " + message.Length);
+ await stream.WriteAsync(message, 0, message.Length);
+ await stream.FlushAsync();
+ Helper.Log.Write(Helper.eLogType.Info, "SendMessageAndReceiveReply: Data sent");
+ _ = ReadImageReply();
+
+ }
+ }
+ catch (Exception ex)
+ {
+ Helper.Log.Write(Helper.eLogType.Error, "SendMessageAndReceiveReply: Exception (closing tcp client now) Sending/Receiving: " + ex.Message);
+ DisconnectClient();
+ return;
+ }
+ }
+
+ }
+}
diff --git a/HyperTizen/SDK/Filestealer.cs b/HyperTizen/SDK/Filestealer.cs
new file mode 100644
index 0000000..20f8fac
--- /dev/null
+++ b/HyperTizen/SDK/Filestealer.cs
@@ -0,0 +1,100 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using HyperTizen.Helper;
+
+namespace HyperTizen.SDK
+{
+ //Credits to Leonardo Rodrigues for this way to download Tizen Operating System files to USB
+ //Tested only on Tizen 8 yet
+ public static class Filestealer
+ {
+ private static void ScanDirectory(string dir, [NotNull] Action action)
+ {
+ try
+ {
+ foreach (string file in Directory.EnumerateFiles(dir))
+ {
+ try
+ {
+ FileInfo fileInfo = new FileInfo(file);
+
+ if ((fileInfo.Attributes & FileAttributes.ReparsePoint) != 0)
+ {
+ action(file + ".symlink", null);
+
+ continue;
+ }
+
+ action(file, File.ReadAllBytes(file));
+ }
+ catch
+ {
+ action(file + ".blocked", null);
+ }
+ }
+
+ foreach (string subDir in Directory.EnumerateDirectories(dir))
+ {
+ DirectoryInfo fileInfo = new DirectoryInfo(subDir);
+
+ if ((fileInfo.Attributes & FileAttributes.ReparsePoint) != 0)
+ {
+ continue;
+ }
+
+ ScanDirectory(subDir, action);
+ }
+ }
+ catch { }
+ }
+ public static void CopyToUsb()
+ {
+ _ = Task.Run(() =>
+ {
+
+ try
+ {
+ ScanDirectory("/usr/bin", (file, bytes) =>
+ {
+ try
+ {
+ Log.Write(eLogType.Debug,$"- Downloading: {file}");
+
+ string fileRelative = file.TrimStart(Path.DirectorySeparatorChar);
+ string fileTarget = Path.Combine(
+ "/opt/media/USBDriveA1",
+ fileRelative
+ );
+
+ string fileTargetDir = Path.GetDirectoryName(fileTarget);
+
+ if (!Directory.Exists(fileTargetDir))
+ {
+ _ = Directory.CreateDirectory(fileTargetDir);
+ }
+
+ File.WriteAllBytes(fileTarget, bytes);
+ }
+ catch (Exception ex)
+ {
+ Log.Write(eLogType.Debug,ex.ToString());
+ }
+ }
+ );
+
+ Log.Write(eLogType.Debug, "Scan finished!");
+ }
+ catch (Exception ex)
+ {
+ Log.Write(eLogType.Debug, ex.ToString());
+ }
+ });
+ }
+ }
+}
diff --git a/HyperTizen/SDK/SecVideoCapture.cs b/HyperTizen/SDK/SecVideoCapture.cs
new file mode 100644
index 0000000..14220e8
--- /dev/null
+++ b/HyperTizen/SDK/SecVideoCapture.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using static HyperTizen.SDK.SecVideoCapture;
+
+namespace HyperTizen.SDK
+{
+ public static unsafe class SecVideoCaptureT7 //for Tizen 7 and below
+ {
+ [DllImport("/usr/lib/libsec-video-capture.so.0", CallingConvention = CallingConvention.Cdecl, EntryPoint = "secvideo_api_capture_screen_unlock")]
+ unsafe public static extern int CaptureScreenUnlock();
+ [DllImport("/usr/lib/libsec-video-capture.so.0", CallingConvention = CallingConvention.Cdecl, EntryPoint = "secvideo_api_capture_screen")] //record with ui
+ unsafe public static extern int CaptureScreen(int w, int h, ref Info_t pInfo);
+ [DllImport("/usr/lib/libsec-video-capture.so.0", CallingConvention = CallingConvention.Cdecl, EntryPoint = "secvideo_api_capture_screen_video_only")] // without ui
+ unsafe public static extern int CaptureScreenVideo(int w, int h, ref Info_t pInfo);
+ [DllImport("/usr/lib/libsec-video-capture.so.0", CallingConvention = CallingConvention.Cdecl, EntryPoint = "secvideo_api_capture_screen_video_only_crop")] // cropped
+ unsafe public static extern int CaptureScreenCrop(int w, int h, ref Info_t pInfo, int iCapture3DMode, int cropW, int cropH);
+ [DllImport("/usr/lib/libsec-video-capture.so.0", CallingConvention = CallingConvention.Cdecl, EntryPoint = "secvideo_api_capture_screen_no_lock_no_copy")] // unknown
+ unsafe public static extern int CaptureScreenNoLocknoCopy(int w, int h, ref Info_t pInfo);
+ //Main Func Errors:
+ //-1 "Input Pram is Wrong"
+ //-1,-2,-3,-5...negative numbers without 4 "Failed scaler_capture"
+
+ //Sub Func Errors
+ //-2 Error: capture type %s, plane %s video only %d
+ //-1 req size less or equal that crop size or non video for videoonly found
+ //-1 Home Screen & yt crop size, capture lock, video info related
+ //-4 Netflix/ Widevine Drm Stuff
+
+ }
+
+ public static unsafe class SecVideoCaptureT8 //for Tizen 8 and above
+ {
+
+ [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
+ public unsafe delegate int CaptureScreenDelegate(IntPtr @this, int w, int h, ref Info_t pInfo);
+ public unsafe struct IVideoCapture
+ {
+ public IntPtr* vtable;
+ }
+
+ private static IVideoCapture* instance;
+ private static CaptureScreenDelegate captureScreen;
+
+ // Muss importiert sein, wenn getInstance exportiert wird
+ [DllImport("/usr/lib/libvideo-capture.so.0.1.0", CallingConvention = CallingConvention.Cdecl, EntryPoint = "getInstance")]
+ private static extern IVideoCapture* GetInstance();
+
+ public static void Init()
+ {
+ instance = GetInstance();
+
+ if (instance == null)
+ Helper.Log.Write(Helper.eLogType.Error, "IVideoCapture instance is null");
+
+ const int CaptureScreenVTableIndex = 3;//
+
+ IntPtr fp = instance->vtable[CaptureScreenVTableIndex];
+ captureScreen = (CaptureScreenDelegate)Marshal.GetDelegateForFunctionPointer(fp, typeof(CaptureScreenDelegate));
+ }
+
+ public static int CaptureScreen(int w, int h, ref Info_t pInfo)
+ {
+ if (captureScreen == null)
+ Helper.Log.Write(Helper.eLogType.Error, "SecVideoCaptureNew not initialized");
+
+ return captureScreen((IntPtr)instance, w, h, ref pInfo);
+ }
+
+ }
+
+ public static class SecVideoCapture
+ {
+
+ public static unsafe int CaptureScreen(int w, int h, ref Info_t pInfo)
+ {
+ if (SystemInfo.TizenVersionMajor >= 8)
+ {
+ // Init should only be done once
+ SecVideoCaptureT8.Init();
+ return SecVideoCaptureT8.CaptureScreen(w, h, ref pInfo);
+ }
+ else
+ {
+ return SecVideoCaptureT7.CaptureScreen(w, h, ref pInfo);
+ }
+ }
+ [StructLayout(LayoutKind.Sequential)]
+ unsafe public struct Info_t
+ {
+ unsafe public Int32 iGivenBufferSize1 { get; set; } //a6[0] = 0 //ref: "C Buffer Size is too small. needed %d bytes but given %d bytes [%d:%s]" needs to be = iGivenBufferSize2
+ unsafe public Int32 iGivenBufferSize2 { get; set; } //a6[1] = 4 //ref: "C Buffer Size is too small. needed %d bytes but given %d bytes [%d:%s]" needs to be = iGivenBufferSize1
+ unsafe public Int32 iWidth { get; set; } //a6[2] = 8 //ref: IceWater "caputre_param.ret_width"
+ unsafe public Int32 iHeight { get; set; } //a6[3] = 12 //ref: IceWater "caputre_param.ret_height"
+ unsafe public IntPtr pImageY { get; set; } //a6[4] // = 16 dest of memcopy copys v31 in adress with sizeof(needed buffer size(i think)) into this
+ unsafe public IntPtr pImageUV { get; set; } //a6[5] // = 20 use this! dest of memcopy copys v223 in adress with sizeof(needed buffer size) into this
+ unsafe public Int32 iRetColorFormat { get; set; } //a6[6] // = 24 //ref: IceWater "color format is"(YUV420 = 0, YUV422 = 1, YUV444 = 2 , None = 3, Everything else = Error)
+ unsafe public Int32 unknown2 { get; set; } //a6[7] // = 28
+ unsafe public Int32 capture3DMode { get; set; } // = 32 //ref: "Capture 3D Mode is DRM_SDP_3D_2D [%d:%s]" (DRM_SDP_3D_2D = 0, DRM_SDP_3D_FRAMEPACKING = 1, DRM_SDP_3D_FRAMESEQ = 2, DRM_SDP_3D_TOPBOTTOM = 3, DRM_SDP_3D_SIDEBYSIDE = 4)
+ //unk3 a6[15] // = 60
+ }
+
+ }
+}
diff --git a/HyperTizen/SDK/SystemInfo.cs b/HyperTizen/SDK/SystemInfo.cs
new file mode 100644
index 0000000..b515211
--- /dev/null
+++ b/HyperTizen/SDK/SystemInfo.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HyperTizen.SDK
+{
+ public static class SystemInfo
+ {
+ public static int TizenVersionMajor
+ {
+ get
+ {
+ string version;
+ Tizen.System.Information.TryGetValue("http://tizen.org/feature/platform.version", out version);
+ return int.Parse(version.Split('.')[0]);
+ }
+ }
+ public static int TizenVersionMinor
+ {
+ get
+ {
+ string version;
+ Tizen.System.Information.TryGetValue("http://tizen.org/feature/platform.version", out version);
+ return int.Parse(version.Split('.')[1]);
+ }
+ }
+ public static bool ImageCapture
+ {
+ get
+ {
+ bool isSupported;
+ Tizen.System.Information.TryGetValue("http://tizen.org/feature/media.image_capture", out isSupported);
+ return isSupported;
+ }
+ }
+ public static bool VideoRecording
+ {
+ get
+ {
+ bool isSupported;
+ Tizen.System.Information.TryGetValue("http://tizen.org/feature/media.video_recording", out isSupported);
+ return isSupported;
+ }
+ }
+ public static int ScreenWidth
+ {
+ get
+ {
+ int width;
+ Tizen.System.Information.TryGetValue("http://tizen.org/feature/screen.width", out width);
+ return width;
+ }
+ }
+ public static int ScreenHeight
+ {
+ get
+ {
+ int height;
+ Tizen.System.Information.TryGetValue("http://tizen.org/feature/screen.height", out height);
+ return height;
+ }
+ }
+
+ public static string ModelName
+ {
+ get
+ {
+ string name;
+ Tizen.System.Information.TryGetValue("http://tizen.org/system/model_name", out name);
+ return name;
+ }
+ }
+ }
+}
diff --git a/HyperTizen/VideoCapture.cs b/HyperTizen/VideoCapture.cs
new file mode 100644
index 0000000..7c1af57
--- /dev/null
+++ b/HyperTizen/VideoCapture.cs
@@ -0,0 +1,179 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Threading.Tasks;
+using HyperTizen.SDK;
+using Tizen.Applications;
+using Tizen.Applications.Notifications;
+
+
+namespace HyperTizen
+{
+ public class ImageData
+ {
+ public byte[] yData { get; set; }
+ public byte[] uvData { get; set; }
+ }
+
+
+ public static class VideoCapture
+ {
+ private static IntPtr pImageY;
+ private static IntPtr pImageUV;
+ private static byte[] managedArrayY;
+ private static byte[] managedArrayUV;
+ public static void InitCapture()
+ {
+ try
+ {
+ Marshal.PrelinkAll(typeof(SDK.SecVideoCapture));
+ }
+ catch
+ {
+ Helper.Log.Write(Helper.eLogType.Error, "VideoCapture.InitCapture() Error: Libarys not found. Check if your Tizenversion is supported");
+ }
+
+ int NV12ySize = Globals.Instance.Width * Globals.Instance.Height;
+ int NV12uvSize = (Globals.Instance.Width * Globals.Instance.Height) / 2; // UV-Plane is half as big as Y-Plane in NV12
+ pImageY = Marshal.AllocHGlobal(NV12ySize);
+ pImageUV = Marshal.AllocHGlobal(NV12uvSize);
+ managedArrayY = new byte[NV12ySize];
+ managedArrayUV = new byte[NV12uvSize];
+
+ int TizenVersionMajor = SystemInfo.TizenVersionMajor;
+ int TizenVersionMinor = SystemInfo.TizenVersionMinor;
+ bool ImageCapture = SystemInfo.ImageCapture;
+ bool VideoRecording = SystemInfo.VideoRecording;
+ int ScreenWidth = SystemInfo.ScreenWidth;
+ int ScreenHeight = SystemInfo.ScreenHeight;
+ string ModelName = SystemInfo.ModelName;
+
+ }
+
+ static bool isRunning = true;
+ unsafe public static void DoCapture()
+ {
+ //These lines need to stay here somehow - they arent used but when i delete them the service breaks ??? weird tizen stuff...
+ var width = 480;
+ var height = 270;
+ var uvBufferSizeYUV420 = (width / 2) * (height / 2);
+
+
+ int NV12ySize = Globals.Instance.Width * Globals.Instance.Height;
+ int NV12uvSize = (Globals.Instance.Width * Globals.Instance.Height) / 2; // UV-Plane is half as big as Y-Plane in NV12
+
+ SDK.SecVideoCapture.Info_t info = new SDK.SecVideoCapture.Info_t();
+ info.iGivenBufferSize1 = NV12ySize;
+ info.iGivenBufferSize2 = NV12uvSize;
+ //info.iWidth = width;
+ //info.iHeight = height;
+ info.pImageY = pImageY;
+ info.pImageUV = pImageUV;
+ //info.iRetColorFormat = 0;
+ //info.capture3DMode = 0;
+ var watchFPS = System.Diagnostics.Stopwatch.StartNew();
+ int result = SDK.SecVideoCapture.CaptureScreen(Globals.Instance.Width, Globals.Instance.Height, ref info); //call itself takes 35-40ms in debug mode so it should be 28-25fps
+ watchFPS.Stop();
+ var elapsedFPS = 1 / watchFPS.Elapsed.TotalSeconds;
+ Helper.Log.Write(Helper.eLogType.Performance, "SDK.SecVideoCapture.CaptureScreen FPS: " + elapsedFPS);
+ Helper.Log.Write(Helper.eLogType.Performance, "SDK.SecVideoCapture.CaptureScreen elapsed ms: " + watchFPS.ElapsedMilliseconds);
+ if (result < 0) //only send Notification once
+ {
+ if(isRunning)
+ switch (result)
+ {
+ case -4:
+ Helper.Log.Write(Helper.eLogType.Error, "SDK.SecVideoCapture.CaptureScreen Result: -4 [Netflix/ Widevine Drm Error]. Seems like you are watching DRM protected content. Capture is not supported for that yet");
+ break;
+ case -1:
+ Helper.Log.Write(Helper.eLogType.Error, "SDK.SecVideoCapture.CaptureScreen Result: -1 [Input Pram is wrong / req size less or equal that crop size / non video for videoonly found]. This can occur when Settings or Video Inputs of the TV change. Check in HyperHDR if the Live-View is still showing an image.");
+ break;
+ case -2:
+ Helper.Log.Write(Helper.eLogType.Error, "SDK.SecVideoCapture.CaptureScreen Result: -2 [capture type %s, plane %s video only %d / Failed scaler_capture]. Please try restarting the TV (coldboot)");
+ //Application.Current.Exit();
+ break;
+ default:
+ Helper.Log.Write(Helper.eLogType.Error, "SDK.SecVideoCapture.CaptureScreen Result: "+ result + " New Error Occured. Please report the shown Number on Github. Also enable every Log Option in the UI, run the Service in Debug Mode and send the Logs.");
+ break;
+ }
+ isRunning = false;
+ return;
+ }
+
+ isRunning = true;
+
+
+ Marshal.Copy(info.pImageY, managedArrayY, 0, NV12ySize);
+ Marshal.Copy(info.pImageUV, managedArrayUV, 0, NV12uvSize);
+
+ bool hasAllZeroes1 = managedArrayY.All(singleByte => singleByte == 0);
+ bool hasAllZeroes2 = managedArrayUV.All(singleByte => singleByte == 0);
+ if (hasAllZeroes1 && hasAllZeroes2)
+ throw new Exception("Sanity check Error");
+
+ Helper.Log.Write(Helper.eLogType.Info, "DoCapture: NV12ySize: " + managedArrayY.Length);
+ //Debug.WriteLine(Convert.ToBase64String(managedArrayY).Length);
+ //Debug.WriteLine(Convert.ToBase64String(managedArrayY));
+ //Debug.WriteLine(Convert.ToBase64String(managedArrayUV));
+
+ //Networking.SendImage(managedArrayY, managedArrayUV, Globals.Instance.Width, Globals.Instance.Height);
+ //Task.Run( ()=>Networking.SendImageAsync(managedArrayY, managedArrayUV, Globals.Instance.Width, Globals.Instance.Height)); doenst work after a few sec
+ //Networking.SendImageAsync(managedArrayY, managedArrayUV, Globals.Instance.Width, Globals.Instance.Height); //100-150ms in debug mode
+ _ = Networking.SendImageAsync(managedArrayY, managedArrayUV,Globals.Instance.Width, Globals.Instance.Height);
+ return;
+ }
+
+ unsafe public static void DoDummyCapture()
+ {
+ int NV12ySize = Globals.Instance.Width * Globals.Instance.Height;
+ int NV12uvSize = (Globals.Instance.Width * Globals.Instance.Height) / 2; // UV-Plane is half as big as Y-Plane in NV12
+ byte[] managedArrayY = new byte[NV12ySize];
+ byte[] managedArrayUV = new byte[NV12uvSize];
+ (managedArrayY, managedArrayUV) = GenerateDummyYUVColor(Globals.Instance.Width, Globals.Instance.Height);
+ _ = Networking.SendImageAsync(managedArrayY, managedArrayUV, Globals.Instance.Width, Globals.Instance.Height);
+ return;
+ }
+
+ public static (byte[] yData, byte[] uvData) GenerateDummyYUVRandom(int width, int height)
+ {
+ int ySize = width * height;
+ int uvSize = (width * height) / 2;
+
+ byte[] yData = new byte[ySize];
+ byte[] uvData = new byte[uvSize];
+
+ Random rnd = new Random();
+ rnd.NextBytes(yData);
+ rnd.NextBytes(uvData);
+
+ return (yData, uvData);
+ }
+
+ public static (byte[] yData, byte[] uvData) GenerateDummyYUVColor(int width, int height)
+ {
+ int ySize = width * height;
+ int uvSize = (width * height) / 2;
+
+ byte[] yData = new byte[ySize];
+ byte[] uvData = new byte[uvSize];
+
+
+ for (int i = 0; i < ySize; i++)
+ {
+ yData[i] = 128;
+ }
+
+ for (int i = 0; i < uvSize; i += 2)
+ {
+ uvData[i] = 128;
+ uvData[i + 1] = 255;
+ }
+
+ return (yData, uvData);
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/HyperTizen/WebSocket/HyperionClient.cs b/HyperTizen/WebSocket/HyperionClient.cs
deleted file mode 100644
index bc940b5..0000000
--- a/HyperTizen/WebSocket/HyperionClient.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-using Newtonsoft.Json;
-using System.Threading.Tasks;
-using Tizen.Applications;
-using HyperTizen.WebSocket.DataTypes;
-using System.Net.WebSockets;
-using System.Text;
-using System;
-using System.Threading;
-
-namespace HyperTizen.WebSocket
-{
- internal class HyperionClient
- {
- WebSocketClient client;
- public HyperionClient()
- {
- if (!Preference.Contains("rpcServer")) return;
- client = new WebSocketClient(Preference.Get("rpcServer"));
- Task.Run(() => client.ConnectAsync());
- Task.Run(() => Start());
- }
-
- public void UpdateURI(string uri)
- {
- if (client?.client != null && client.client.State == WebSocketState.Open)
- {
- client.client.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
- }
-
- client = new WebSocketClient(uri);
- Task.Run(() => client.ConnectAsync());
- }
-
- public async Task Start(bool shouldStart = false)
- {
- if (client != null && Capturer.GetCondition())
- {
- while (App.Configuration.Enabled || shouldStart)
- {
- Color[] colors = Capturer.GetColors();
- string image = Capturer.ToImage(colors);
-
- if (client?.client?.State == WebSocketState.Open)
- {
- ImageCommand imgCmd = new ImageCommand(image);
- string message = JsonConvert.SerializeObject(imgCmd);
- var buffer = Encoding.UTF8.GetBytes(message);
- await client.client.SendAsync(new ArraySegment(buffer), WebSocketMessageType.Text, true, CancellationToken.None);
- }
-
- if (App.Configuration.Enabled && shouldStart) shouldStart = false;
- else if (!App.Configuration.Enabled && shouldStart) App.Configuration.Enabled = true;
- }
- }
- }
-
- public async Task Stop()
- {
- if (App.Configuration.Enabled) App.Configuration.Enabled = false;
- Color[] colors = Capturer.GetColors();
- string image = Capturer.ToImage(colors);
-
- if (client?.client?.State == WebSocketState.Open)
- {
- ImageCommand imgCmd = new ImageCommand(image);
- string message = JsonConvert.SerializeObject(imgCmd);
- var buffer = Encoding.UTF8.GetBytes(message);
- await client.client.SendAsync(new ArraySegment(buffer), WebSocketMessageType.Text, true, CancellationToken.None);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/HyperTizen/WebSocket/WebSocket.cs b/HyperTizen/WebSocket/WebSocket.cs
index 876c83f..d845ef2 100644
--- a/HyperTizen/WebSocket/WebSocket.cs
+++ b/HyperTizen/WebSocket/WebSocket.cs
@@ -139,7 +139,7 @@ void SetConfiguration(SetConfigEvent setConfigEvent)
case "rpcServer":
{
App.Configuration.RPCServer = setConfigEvent.value;
- App.client.UpdateURI(setConfigEvent.value);
+ //App.client.UpdateURI(setConfigEvent.value);
break;
}
case "enabled":
@@ -148,7 +148,7 @@ void SetConfiguration(SetConfigEvent setConfigEvent)
if (!App.Configuration.Enabled && value)
{
App.Configuration.Enabled = value;
- Task.Run(() => App.client.Start(value));
+ Task.Run(() => App.client.Start());
}
else App.Configuration.Enabled = value;
break;
diff --git a/HyperTizen/tizen-manifest.xml b/HyperTizen/tizen-manifest.xml
index 59fe390..b145920 100644
--- a/HyperTizen/tizen-manifest.xml
+++ b/HyperTizen/tizen-manifest.xml
@@ -1,8 +1,8 @@
-
+
Reis Can
-
+
HyperTizen.png
diff --git a/HyperTizen/tizen_dotnet_project.yaml b/HyperTizen/tizen_dotnet_project.yaml
index c9c52c1..798149d 100644
--- a/HyperTizen/tizen_dotnet_project.yaml
+++ b/HyperTizen/tizen_dotnet_project.yaml
@@ -1,9 +1,9 @@
-# csproj file path
-csproj_file: HyperTizen.csproj
-
-# files monitored for dirty/modified status
-files:
- - HyperTizen.csproj
- - HyperTizen_App.cs
- - tizen-manifest.xml
- - shared/res/HyperTizen.png
\ No newline at end of file
+# csproj file path
+csproj_file: HyperTizen.csproj
+
+# files monitored for dirty/modified status
+files:
+ - HyperTizen.csproj
+ - HyperTizen_App.cs
+ - tizen-manifest.xml
+ - shared/res/HyperTizen.png
diff --git a/docs/README.md b/docs/README.md
index f73be93..b224f3d 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -4,7 +4,7 @@ HyperTizen is a Hyperion / HyperHDR capturer for Tizen TVs.
# Installation
-To install HyperTizen, you need to have a Samsung TV (Tizen) that has at least Tizen 6.5 (2022+).
+To install HyperTizen, you need to have a Samsung TV (Tizen).
You'll need Tizen Studio to install the app on your TV. You can download it from the [official website](https://developer.samsung.com/smarttv/develop/getting-started/setting-up-sdk/installing-tv-sdk.html).
@@ -39,4 +39,4 @@ tizen package -t tpk -s YourProfileName -o path/to/output/dir -- path/to/io.gh.r
# tizen package -t tpk -s HyperTizen -o release -- io.gh.reisxd.HyperTizen.tpk
```
-4. You should now be able to install the package.
\ No newline at end of file
+4. You should now be able to install the package.